Import SpiderMonkey Temporal tests

Temporal tests written for the SpiderMonkey implementation. Mostly
covers edge cases around mathematical operations and regression tests
for reported spec bugs.
This commit is contained in:
André Bargull 2022-07-05 12:48:26 +02:00 committed by Philip Chimento
parent 6685c6c81c
commit 30091032c1
19 changed files with 644 additions and 0 deletions

View File

@ -0,0 +1,60 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.instant.prototype.add
description: >
Instant is minimum/maximum instant.
features: [Temporal]
---*/
let min = new Temporal.Instant(-86_40000_00000_00000_00000n);
let max = new Temporal.Instant(86_40000_00000_00000_00000n);
let zero = Temporal.Duration.from({nanoseconds: 0});
let one = Temporal.Duration.from({nanoseconds: 1});
let minusOne = Temporal.Duration.from({nanoseconds: -1});
assert.sameValue(min.add(zero).epochNanoseconds, min.epochNanoseconds,
"Adding zero to the minimum instant");
assert.sameValue(max.add(zero).epochNanoseconds, max.epochNanoseconds,
"Adding zero to the maximum instant");
assert.throws(RangeError, () => min.add(minusOne),
"Subtracting one from the minimum instant");
assert.throws(RangeError, () => max.add(one),
"Adding one to the maximum instant");
assert.sameValue(min.add(one).epochNanoseconds, min.epochNanoseconds + 1n,
"Adding one to the minimum instant");
assert.sameValue(max.add(minusOne).epochNanoseconds, max.epochNanoseconds - 1n,
"Subtracting one from the maximum instant");
// From minimum to maximum instant.
assert.sameValue(min.add({nanoseconds: 86_40000_00000_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds,
"Minimum to maximum instant by adding nanoseconds");
assert.sameValue(min.add({microseconds: 8640_00000_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds,
"Minimum to maximum instant by adding microseconds");
assert.sameValue(min.add({milliseconds: 8_64000_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds,
"Minimum to maximum instant by adding milliseconds");
assert.sameValue(min.add({seconds: 864_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds,
"Minimum to maximum instant by adding seconds");
// From maximum to minimum instant.
assert.sameValue(max.add({nanoseconds: -86_40000_00000_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds,
"Maximum to minimum instant by adding nanoseconds");
assert.sameValue(max.add({microseconds: -8640_00000_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds,
"Maximum to minimum instant by adding microseconds");
assert.sameValue(max.add({milliseconds: -8_64000_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds,
"Maximum to minimum instant by adding milliseconds");
assert.sameValue(max.add({seconds: -864_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds,
"Maximum to minimum instant by adding seconds");

View File

@ -0,0 +1,52 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.instant.prototype.subtract
description: >
Instant is minimum/maximum instant.
features: [Temporal]
---*/
let min = new Temporal.Instant(-86_40000_00000_00000_00000n);
let max = new Temporal.Instant(86_40000_00000_00000_00000n);
let zero = Temporal.Duration.from({nanoseconds: 0});
let one = Temporal.Duration.from({nanoseconds: 1});
let minusOne = Temporal.Duration.from({nanoseconds: -1});
// Adding zero to the minimum instant.
assert.sameValue(min.subtract(zero).epochNanoseconds, min.epochNanoseconds);
// Adding zero to the maximum instant.
assert.sameValue(max.subtract(zero).epochNanoseconds, max.epochNanoseconds);
// Subtracting one from the minimum instant.
assert.throws(RangeError, () => min.subtract(one));
// Adding one to the maximum instant.
assert.throws(RangeError, () => max.subtract(minusOne));
// Adding one to the minimum instant.
assert.sameValue(min.subtract(minusOne).epochNanoseconds, min.epochNanoseconds + 1n);
// Subtracting one from the maximum instant.
assert.sameValue(max.subtract(one).epochNanoseconds, max.epochNanoseconds - 1n);
// From minimum to maximum instant.
assert.sameValue(min.subtract({nanoseconds: -86_40000_00000_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds);
assert.sameValue(min.subtract({microseconds: -8640_00000_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds);
assert.sameValue(min.subtract({milliseconds: -8_64000_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds);
assert.sameValue(min.subtract({seconds: -864_00000_00000 * 2}).epochNanoseconds, max.epochNanoseconds);
// From maximum to minimum instant.
assert.sameValue(max.subtract({nanoseconds: 86_40000_00000_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds);
assert.sameValue(max.subtract({microseconds: 8640_00000_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds);
assert.sameValue(max.subtract({milliseconds: 8_64000_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds);
assert.sameValue(max.subtract({seconds: 864_00000_00000 * 2}).epochNanoseconds, min.epochNanoseconds);

View File

@ -0,0 +1,107 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.round
description: >
Round smallestUnit "day" with various rounding modes.
info: |
Temporal.ZonedDateTime.prototype.round ( roundTo )
...
18. Let dayLengthNs be (endNs - startNs).
...
20. Let roundResult be ! RoundISODateTime(temporalDateTime.[[ISOYear]],
temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], temporalDateTime.[[ISOHour]],
temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]],
temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]],
temporalDateTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode,
dayLengthNs).
...
RoundISODateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond,
increment, unit, roundingMode [ , dayLength ] )
...
4. Let roundedTime be ! RoundTime(hour, minute, second, millisecond, microsecond, nanosecond,
increment, unit, roundingMode, dayLength).
...
RoundTime ( hour, minute, second, millisecond, microsecond, nanosecond, increment, unit,
roundingMode [ , dayLengthNs ] )
...
4. If unit is "day", then
...
b. Let quantity be (((((hour × 60 + minute) × 60 + second) × 1000 + millisecond) × 1000 +
microsecond) × 1000 + nanosecond) / dayLengthNs.
...
features: [Temporal]
---*/
class TimeZone extends Temporal.TimeZone {
#count = 0;
#nanoseconds;
constructor(nanoseconds) {
super("UTC");
this.#nanoseconds = nanoseconds;
}
getPossibleInstantsFor(dateTime) {
if (++this.#count === 2) {
return [new Temporal.Instant(this.#nanoseconds)];
}
return super.getPossibleInstantsFor(dateTime);
}
}
function test(epochNanoseconds, tomorrowEpochNanoseconds, testCases) {
for (let [roundingMode, expected] of Object.entries(testCases)) {
let timeZone = new TimeZone(tomorrowEpochNanoseconds);
let zoned = new Temporal.ZonedDateTime(epochNanoseconds, timeZone);
let result = zoned.round({ smallestUnit: "days", roundingMode });
assert.sameValue(result.epochNanoseconds, expected);
}
}
const oneDay = 24n * 60n * 60n * 1000n * 1000n * 1000n;
// Test positive divisor (dayLengthNs).
test(3n, 10n, {
ceil: oneDay,
floor: 0n,
trunc: 0n,
halfExpand: 0n,
});
test(-3n, 10n, {
ceil: 0n,
floor: -oneDay,
trunc: -oneDay,
halfExpand: 0n,
});
// Test negative divisor (dayLengthNs).
test(3n, -10n, {
ceil: 0n,
floor: -oneDay,
trunc: 0n,
halfExpand: 0n,
});
test(-3n, -10n, {
ceil: oneDay,
floor: 0n,
trunc: 0n,
halfExpand: 0n,
});
// Test values at int64 boundaries.
test(3n, /*INT64_MAX=*/ 9223372036854775807n, {
ceil: oneDay,
floor: 0n,
trunc: 0n,
halfExpand: 0n,
});
test(3n, /*INT64_MIN=*/ -9223372036854775808n, {
ceil: 0n,
floor: -oneDay,
trunc: 0n,
halfExpand: 0n,
});

View File

@ -0,0 +1,19 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Africa/Asmera": "Africa/Asmara",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,37 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"America/Atka": "America/Adak",
"America/Buenos_Aires": "America/Argentina/Buenos_Aires",
"America/Catamarca": "America/Argentina/Catamarca",
"America/Cordoba": "America/Argentina/Cordoba",
"America/Fort_Wayne": "America/Indiana/Indianapolis",
"America/Godthab": "America/Nuuk",
"America/Indianapolis": "America/Indiana/Indianapolis",
"America/Jujuy": "America/Argentina/Jujuy",
"America/Knox_IN": "America/Indiana/Knox",
"America/Kralendijk": "America/Curacao",
"America/Louisville": "America/Kentucky/Louisville",
"America/Lower_Princes": "America/Curacao",
"America/Marigot": "America/Port_of_Spain",
"America/Mendoza": "America/Argentina/Mendoza",
"America/Porto_Acre": "America/Rio_Branco",
"America/Santa_Isabel": "America/Tijuana",
"America/Shiprock": "America/Denver",
"America/St_Barthelemy": "America/Port_of_Spain",
"America/Virgin": "America/St_Thomas",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Antarctica/South_Pole": "Antarctica/McMurdo",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Arctic/Longyearbyen": "Europe/Oslo",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,30 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Asia/Ashkhabad": "Asia/Ashgabat",
"Asia/Calcutta": "Asia/Kolkata",
"Asia/Chungking": "Asia/Chongqing",
"Asia/Dacca": "Asia/Dhaka",
"Asia/Istanbul": "Europe/Istanbul",
"Asia/Katmandu": "Asia/Kathmandu",
"Asia/Macao": "Asia/Macau",
"Asia/Rangoon": "Asia/Yangon",
"Asia/Saigon": "Asia/Ho_Chi_Minh",
"Asia/Thimbu": "Asia/Thimphu",
"Asia/Ujung_Pandang": "Asia/Makassar",
"Asia/Ulan_Bator": "Asia/Ulaanbaatar",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Atlantic/Faeroe": "Atlantic/Faroe",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,29 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Australia/ACT": "Australia/Sydney",
"Australia/Canberra": "Australia/Sydney",
"Australia/LHI": "Australia/Lord_Howe",
"Australia/NSW": "Australia/Sydney",
"Australia/North": "Australia/Darwin",
"Australia/Queensland": "Australia/Brisbane",
"Australia/South": "Australia/Adelaide",
"Australia/Tasmania": "Australia/Hobart",
"Australia/Victoria": "Australia/Melbourne",
"Australia/West": "Australia/Perth",
"Australia/Yancowinna": "Australia/Broken_Hill",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,22 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Brazil/Acre": "America/Rio_Branco",
"Brazil/DeNoronha": "America/Noronha",
"Brazil/East": "America/Sao_Paulo",
"Brazil/West": "America/Manaus",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,26 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Canada/Atlantic": "America/Halifax",
"Canada/Central": "America/Winnipeg",
"Canada/Eastern": "America/Toronto",
"Canada/Mountain": "America/Edmonton",
"Canada/Newfoundland": "America/St_Johns",
"Canada/Pacific": "America/Vancouver",
"Canada/Saskatchewan": "America/Regina",
"Canada/Yukon": "America/Whitehorse",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,20 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Chile/Continental": "America/Santiago",
"Chile/EasterIsland": "Pacific/Easter",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Europe/Bratislava": "Europe/Prague",
"Europe/Busingen": "Europe/Zurich",
"Europe/Mariehamn": "Europe/Helsinki",
"Europe/Nicosia": "Asia/Nicosia",
"Europe/Podgorica": "Europe/Belgrade",
"Europe/San_Marino": "Europe/Rome",
"Europe/Vatican": "Europe/Rome",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,21 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Mexico/BajaNorte": "America/Tijuana",
"Mexico/BajaSur": "America/Mazatlan",
"Mexico/General": "America/Mexico_City",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,22 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Pacific/Ponape": "Pacific/Pohnpei",
"Pacific/Samoa": "Pacific/Pago_Pago",
"Pacific/Truk": "Pacific/Chuuk",
"Pacific/Yap": "Pacific/Chuuk",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,30 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"US/Alaska": "America/Anchorage",
"US/Aleutian": "America/Adak",
"US/Arizona": "America/Phoenix",
"US/Central": "America/Chicago",
"US/East-Indiana": "America/Indiana/Indianapolis",
"US/Eastern": "America/New_York",
"US/Hawaii": "Pacific/Honolulu",
"US/Indiana-Starke": "America/Indiana/Knox",
"US/Michigan": "America/Detroit",
"US/Mountain": "America/Denver",
"US/Pacific": "America/Los_Angeles",
"US/Samoa": "Pacific/Pago_Pago",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,50 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Cuba": "America/Havana",
"Egypt": "Africa/Cairo",
"Eire": "Europe/Dublin",
"GB": "Europe/London",
"GB-Eire": "Europe/London",
"GMT": "UTC",
"GMT0": "UTC",
"GMT+0": "UTC",
"GMT-0": "UTC",
"Greenwich": "UTC",
"Hongkong": "Asia/Hong_Kong",
"Iceland": "Atlantic/Reykjavik",
"Iran": "Asia/Tehran",
"Israel": "Asia/Jerusalem",
"Jamaica": "America/Jamaica",
"Japan": "Asia/Tokyo",
"Kwajalein": "Pacific/Kwajalein",
"Libya": "Africa/Tripoli",
"NZ": "Pacific/Auckland",
"NZ-CHAT": "Pacific/Chatham",
"Navajo": "America/Denver",
"PRC": "Asia/Shanghai",
"Poland": "Europe/Warsaw",
"Portugal": "Europe/Lisbon",
"ROC": "Asia/Taipei",
"ROK": "Asia/Seoul",
"Singapore": "Asia/Singapore",
"Turkey": "Europe/Istanbul",
"UCT": "UTC",
"Universal": "UTC",
"W-SU": "Europe/Moscow",
"Zulu": "UTC",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}

View File

@ -0,0 +1,37 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor
description: >
Test offset when nanoseconds are subtracted or added from DST transition.
features: [Temporal]
---*/
// From <https://github.com/eggert/tz/blob/main/northamerica>:
//
// # Rule NAME FROM TO - IN ON AT SAVE LETTER
// Rule CA 1950 1966 - Apr lastSun 1:00 1:00 D
//
// # Zone NAME STDOFF RULES FORMAT [UNTIL]
// Zone America/Los_Angeles -7:52:58 - LMT 1883 Nov 18 12:07:02
// -8:00 US P%sT 1946
// -8:00 CA P%sT 1967
// -8:00 US P%sT
let tz = new Temporal.TimeZone("America/Los_Angeles");
let p = Temporal.Instant.from("1965-04-25T09:00:00Z");
const nsPerHour = 60 * 60 * 1000**3;
assert.sameValue(tz.getOffsetNanosecondsFor(p),
-7 * nsPerHour,
"DST transition");
assert.sameValue(tz.getOffsetNanosecondsFor(p.add({nanoseconds: +1})),
-7 * nsPerHour,
"DST transition plus one nanosecond");
assert.sameValue(tz.getOffsetNanosecondsFor(p.add({nanoseconds: -1})),
-8 * nsPerHour,
"DST transition minus one nanosecond");