blob: fc78d24b7e93ca03bd40b6ba76870002bebf5401 [file] [log] [blame]
var BUGNUMBER;
var summary;
function runDSTOffsetCachingTestsFraction(part, parts)
{
BUGNUMBER = 563938;
summary = 'Cache DST offsets to improve SunSpider score';
print(BUGNUMBER + ": " + summary);
var MAX_UNIX_TIMET = 2145859200;
var RANGE_EXPANSION_AMOUNT = 30 * 24 * 60 * 60;
/**
* Computes the time zone offset in minutes at the given timestamp.
*/
function tzOffsetFromUnixTimestamp(timestamp)
{
var d = new Date(NaN);
d.setTime(timestamp); // local slot = NaN, UTC slot = timestamp
return d.getTimezoneOffset(); // get UTC, calculate local => diff in minutes
}
/**
* Clear the DST offset cache, leaving it initialized to include a timestamp
* completely unlike the provided one (i.e. one very, very far away in time
* from it). Thus an immediately following lookup for the provided timestamp
* will cache-miss and compute a clean value.
*/
function clearDSTOffsetCache(undesiredTimestamp)
{
var opposite = (undesiredTimestamp + MAX_UNIX_TIMET / 2) % MAX_UNIX_TIMET;
// Generic purge to known, but not necessarily desired, state
tzOffsetFromUnixTimestamp(0);
tzOffsetFromUnixTimestamp(MAX_UNIX_TIMET);
// Purge to desired state. Cycle 2x in case opposite or undesiredTimestamp
// is close to 0 or MAX_UNIX_TIMET.
tzOffsetFromUnixTimestamp(opposite);
tzOffsetFromUnixTimestamp(undesiredTimestamp);
tzOffsetFromUnixTimestamp(opposite);
tzOffsetFromUnixTimestamp(undesiredTimestamp);
}
function computeCanonicalTZOffset(timestamp)
{
clearDSTOffsetCache(timestamp);
return tzOffsetFromUnixTimestamp(timestamp);
}
var TEST_TIMESTAMPS_SECONDS =
[
// Special-ish timestamps
0,
RANGE_EXPANSION_AMOUNT,
MAX_UNIX_TIMET,
];
var ONE_DAY = 24 * 60 * 60;
var EIGHTY_THREE_HOURS = 83 * 60 * 60;
var NINETY_EIGHT_HOURS = 98 * 60 * 60;
function nextIncrement(i)
{
return i === EIGHTY_THREE_HOURS ? NINETY_EIGHT_HOURS : EIGHTY_THREE_HOURS;
}
// Now add a long sequence of non-special timestamps, from a fixed range, that
// overlaps a DST change by "a bit" on each side. 67 days should be enough
// displacement that we can occasionally exercise the implementation's
// thirty-day expansion and the DST-offset-change logic. Use two different
// increments just to be safe and catch something a single increment might not.
var DST_CHANGE_DATE = 1268553600; // March 14, 2010
for (var t = DST_CHANGE_DATE - 67 * ONE_DAY,
i = nextIncrement(NINETY_EIGHT_HOURS),
end = DST_CHANGE_DATE + 67 * ONE_DAY;
t < end;
i = nextIncrement(i), t += i)
{
TEST_TIMESTAMPS_SECONDS.push(t);
}
var TEST_TIMESTAMPS =
TEST_TIMESTAMPS_SECONDS.map(function(v) { return v * 1000; });
/**************
* BEGIN TEST *
**************/
// Compute the correct time zone offsets for all timestamps to be tested.
var CORRECT_TZOFFSETS = TEST_TIMESTAMPS.map(computeCanonicalTZOffset);
// Intentionally and knowingly invoking every single logic path in the cache
// isn't easy for a human to get right (and know he's gotten it right), so
// let's do it the easy way: exhaustively try all possible four-date sequences
// selecting from our array of possible timestamps.
var sz = TEST_TIMESTAMPS.length;
var start = Math.floor((part - 1) / parts * sz);
var end = Math.floor(part / parts * sz);
print("Exhaustively testing timestamps " +
"[" + start + ", " + end + ") of " + sz + "...");
try
{
for (var i = start; i < end; i++)
{
print("Testing timestamp " + i + "...");
var t1 = TEST_TIMESTAMPS[i];
for (var j = 0; j < sz; j++)
{
var t2 = TEST_TIMESTAMPS[j];
for (var k = 0; k < sz; k++)
{
var t3 = TEST_TIMESTAMPS[k];
for (var w = 0; w < sz; w++)
{
var t4 = TEST_TIMESTAMPS[w];
clearDSTOffsetCache(t1);
var tzo1 = tzOffsetFromUnixTimestamp(t1);
var tzo2 = tzOffsetFromUnixTimestamp(t2);
var tzo3 = tzOffsetFromUnixTimestamp(t3);
var tzo4 = tzOffsetFromUnixTimestamp(t4);
assertEq(tzo1, CORRECT_TZOFFSETS[i]);
assertEq(tzo2, CORRECT_TZOFFSETS[j]);
assertEq(tzo3, CORRECT_TZOFFSETS[k]);
assertEq(tzo4, CORRECT_TZOFFSETS[w]);
}
}
}
}
}
catch (e)
{
assertEq(true, false,
"Error when testing with timestamps " +
i + ", " + j + ", " + k + ", " + w +
" (" + t1 + ", " + t2 + ", " + t3 + ", " + t4 + ")!");
}
reportCompare(true, true);
print("All tests passed!");
}