summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Date/shell.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/src/tests/non262/Date/shell.js311
1 files changed, 311 insertions, 0 deletions
diff --git a/js/src/tests/non262/Date/shell.js b/js/src/tests/non262/Date/shell.js
new file mode 100644
index 0000000000..9246c1eaaa
--- /dev/null
+++ b/js/src/tests/non262/Date/shell.js
@@ -0,0 +1,311 @@
+/**
+ * Date functions used by tests in Date suite
+ */
+(function(global) {
+ const msPerDay = 1000 * 60 * 60 * 24;
+ const msPerHour = 1000 * 60 * 60;
+ global.msPerHour = msPerHour;
+
+ // Offset of tester's time zone from UTC.
+ const TZ_DIFF = GetRawTimezoneOffset();
+ global.TZ_ADJUST = TZ_DIFF * msPerHour;
+
+ const UTC_01_JAN_1900 = -2208988800000;
+ const UTC_01_JAN_2000 = 946684800000;
+ const UTC_29_FEB_2000 = UTC_01_JAN_2000 + 31 * msPerDay + 28 * msPerDay;
+ const UTC_01_JAN_2005 = UTC_01_JAN_2000 + TimeInYear(2000) + TimeInYear(2001) +
+ TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004);
+ global.UTC_01_JAN_1900 = UTC_01_JAN_1900;
+ global.UTC_01_JAN_2000 = UTC_01_JAN_2000;
+ global.UTC_29_FEB_2000 = UTC_29_FEB_2000;
+ global.UTC_01_JAN_2005 = UTC_01_JAN_2005;
+
+ /*
+ * Originally, the test suite used a hard-coded value TZ_DIFF = -8.
+ * But that was only valid for testers in the Pacific Standard Time Zone!
+ * We calculate the proper number dynamically for any tester. We just
+ * have to be careful not to use a date subject to Daylight Savings Time...
+ */
+ function GetRawTimezoneOffset() {
+ let t1 = new Date(2000, 1, 1).getTimezoneOffset();
+ let t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset();
+
+ // 1) Time zone without daylight saving time.
+ // 2) Northern hemisphere with daylight saving time.
+ if ((t1 - t2) >= 0)
+ return -t1 / 60;
+
+ // 3) Southern hemisphere with daylight saving time.
+ return -t2 / 60;
+ }
+
+ function DaysInYear(y) {
+ return y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 366 : 365;
+ }
+
+ function TimeInYear(y) {
+ return DaysInYear(y) * msPerDay;
+ }
+
+ function getDefaultTimeZone() {
+ var tz = getTimeZone();
+ switch (tz) {
+ case "EST":
+ case "EDT":
+ return "EST5EDT";
+
+ case "CST":
+ case "CDT":
+ return "CST6CDT";
+
+ case "MST":
+ case "MDT":
+ return "MST7MDT";
+
+ case "PST":
+ case "PDT":
+ return "PST8PDT";
+
+ default:
+ // Other time zones abbrevations are not supported.
+ return tz;
+ }
+ }
+
+ function getDefaultLocale() {
+ // If the default locale looks like a BCP-47 language tag, return it.
+ var locale = global.getDefaultLocale();
+ if (locale.match(/^[a-z][a-z0-9\-]+$/i))
+ return locale;
+
+ // Otherwise use undefined to reset to the default locale.
+ return undefined;
+ }
+
+ let defaultTimeZone = null;
+ let defaultLocale = null;
+
+ // Run the given test in the requested time zone.
+ function inTimeZone(tzname, fn) {
+ if (defaultTimeZone === null)
+ defaultTimeZone = getDefaultTimeZone();
+
+ setTimeZone(tzname);
+ try {
+ fn();
+ } finally {
+ setTimeZone(defaultTimeZone);
+ }
+ }
+ global.inTimeZone = inTimeZone;
+
+ // Run the given test with the requested locale.
+ function withLocale(locale, fn) {
+ if (defaultLocale === null)
+ defaultLocale = getDefaultLocale();
+
+ setDefaultLocale(locale);
+ try {
+ fn();
+ } finally {
+ setDefaultLocale(defaultLocale);
+ }
+ }
+ global.withLocale = withLocale;
+
+ const Month = {
+ January: 0,
+ February: 1,
+ March: 2,
+ April: 3,
+ May: 4,
+ June: 5,
+ July: 6,
+ August: 7,
+ September: 8,
+ October: 9,
+ November: 10,
+ December: 11,
+ };
+ global.Month = Month;
+
+ const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].join("|");
+ const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].join("|");
+ const datePart = String.raw `(?:${weekdays}) (?:${months}) \d{2}`;
+ const timePart = String.raw `\d{4,6} \d{2}:\d{2}:\d{2} GMT[+-]\d{4}`;
+ const dateTimeRE = new RegExp(String.raw `^(${datePart} ${timePart})(?: \((.+)\))?$`);
+
+ function assertDateTime(date, expected, ...alternativeTimeZones) {
+ let actual = date.toString();
+ assertEq(dateTimeRE.test(expected), true, `${expected}`);
+ assertEq(dateTimeRE.test(actual), true, `${actual}`);
+
+ let [, expectedDateTime, expectedTimeZone] = dateTimeRE.exec(expected);
+ let [, actualDateTime, actualTimeZone] = dateTimeRE.exec(actual);
+
+ assertEq(actualDateTime, expectedDateTime);
+
+ // The time zone identifier is optional, so only compare its value if
+ // it's present in |actual| and |expected|.
+ if (expectedTimeZone !== undefined && actualTimeZone !== undefined) {
+ // Test against the alternative time zone identifiers if necessary.
+ if (actualTimeZone !== expectedTimeZone) {
+ for (let alternativeTimeZone of alternativeTimeZones) {
+ if (actualTimeZone === alternativeTimeZone) {
+ expectedTimeZone = alternativeTimeZone;
+ break;
+ }
+ }
+ }
+ assertEq(actualTimeZone, expectedTimeZone);
+ }
+ }
+ global.assertDateTime = assertDateTime;
+})(this);
+
+
+function runDSTOffsetCachingTestsFraction(part, parts)
+{
+ var BUGNUMBER = 563938;
+ var summary = 'Cache DST offsets to improve SunSpider score';
+
+ print(BUGNUMBER + ": " + summary);
+
+ var MAX_UNIX_TIMET = 2145859200; // "2037-12-31T08:00:00.000Z" (PST8PDT based!)
+ 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!");
+}