|
1 |
|
2 var BUGNUMBER; |
|
3 var summary; |
|
4 |
|
5 function runDSTOffsetCachingTestsFraction(part, parts) |
|
6 { |
|
7 BUGNUMBER = 563938; |
|
8 summary = 'Cache DST offsets to improve SunSpider score'; |
|
9 |
|
10 print(BUGNUMBER + ": " + summary); |
|
11 |
|
12 var MAX_UNIX_TIMET = 2145859200; |
|
13 var RANGE_EXPANSION_AMOUNT = 30 * 24 * 60 * 60; |
|
14 |
|
15 /** |
|
16 * Computes the time zone offset in minutes at the given timestamp. |
|
17 */ |
|
18 function tzOffsetFromUnixTimestamp(timestamp) |
|
19 { |
|
20 var d = new Date(NaN); |
|
21 d.setTime(timestamp); // local slot = NaN, UTC slot = timestamp |
|
22 return d.getTimezoneOffset(); // get UTC, calculate local => diff in minutes |
|
23 } |
|
24 |
|
25 /** |
|
26 * Clear the DST offset cache, leaving it initialized to include a timestamp |
|
27 * completely unlike the provided one (i.e. one very, very far away in time |
|
28 * from it). Thus an immediately following lookup for the provided timestamp |
|
29 * will cache-miss and compute a clean value. |
|
30 */ |
|
31 function clearDSTOffsetCache(undesiredTimestamp) |
|
32 { |
|
33 var opposite = (undesiredTimestamp + MAX_UNIX_TIMET / 2) % MAX_UNIX_TIMET; |
|
34 |
|
35 // Generic purge to known, but not necessarily desired, state |
|
36 tzOffsetFromUnixTimestamp(0); |
|
37 tzOffsetFromUnixTimestamp(MAX_UNIX_TIMET); |
|
38 |
|
39 // Purge to desired state. Cycle 2x in case opposite or undesiredTimestamp |
|
40 // is close to 0 or MAX_UNIX_TIMET. |
|
41 tzOffsetFromUnixTimestamp(opposite); |
|
42 tzOffsetFromUnixTimestamp(undesiredTimestamp); |
|
43 tzOffsetFromUnixTimestamp(opposite); |
|
44 tzOffsetFromUnixTimestamp(undesiredTimestamp); |
|
45 } |
|
46 |
|
47 function computeCanonicalTZOffset(timestamp) |
|
48 { |
|
49 clearDSTOffsetCache(timestamp); |
|
50 return tzOffsetFromUnixTimestamp(timestamp); |
|
51 } |
|
52 |
|
53 var TEST_TIMESTAMPS_SECONDS = |
|
54 [ |
|
55 // Special-ish timestamps |
|
56 0, |
|
57 RANGE_EXPANSION_AMOUNT, |
|
58 MAX_UNIX_TIMET, |
|
59 ]; |
|
60 |
|
61 var ONE_DAY = 24 * 60 * 60; |
|
62 var EIGHTY_THREE_HOURS = 83 * 60 * 60; |
|
63 var NINETY_EIGHT_HOURS = 98 * 60 * 60; |
|
64 function nextIncrement(i) |
|
65 { |
|
66 return i === EIGHTY_THREE_HOURS ? NINETY_EIGHT_HOURS : EIGHTY_THREE_HOURS; |
|
67 } |
|
68 |
|
69 // Now add a long sequence of non-special timestamps, from a fixed range, that |
|
70 // overlaps a DST change by "a bit" on each side. 67 days should be enough |
|
71 // displacement that we can occasionally exercise the implementation's |
|
72 // thirty-day expansion and the DST-offset-change logic. Use two different |
|
73 // increments just to be safe and catch something a single increment might not. |
|
74 var DST_CHANGE_DATE = 1268553600; // March 14, 2010 |
|
75 for (var t = DST_CHANGE_DATE - 67 * ONE_DAY, |
|
76 i = nextIncrement(NINETY_EIGHT_HOURS), |
|
77 end = DST_CHANGE_DATE + 67 * ONE_DAY; |
|
78 t < end; |
|
79 i = nextIncrement(i), t += i) |
|
80 { |
|
81 TEST_TIMESTAMPS_SECONDS.push(t); |
|
82 } |
|
83 |
|
84 var TEST_TIMESTAMPS = |
|
85 TEST_TIMESTAMPS_SECONDS.map(function(v) { return v * 1000; }); |
|
86 |
|
87 /************** |
|
88 * BEGIN TEST * |
|
89 **************/ |
|
90 |
|
91 // Compute the correct time zone offsets for all timestamps to be tested. |
|
92 var CORRECT_TZOFFSETS = TEST_TIMESTAMPS.map(computeCanonicalTZOffset); |
|
93 |
|
94 // Intentionally and knowingly invoking every single logic path in the cache |
|
95 // isn't easy for a human to get right (and know he's gotten it right), so |
|
96 // let's do it the easy way: exhaustively try all possible four-date sequences |
|
97 // selecting from our array of possible timestamps. |
|
98 |
|
99 var sz = TEST_TIMESTAMPS.length; |
|
100 var start = Math.floor((part - 1) / parts * sz); |
|
101 var end = Math.floor(part / parts * sz); |
|
102 |
|
103 print("Exhaustively testing timestamps " + |
|
104 "[" + start + ", " + end + ") of " + sz + "..."); |
|
105 |
|
106 try |
|
107 { |
|
108 for (var i = start; i < end; i++) |
|
109 { |
|
110 print("Testing timestamp " + i + "..."); |
|
111 |
|
112 var t1 = TEST_TIMESTAMPS[i]; |
|
113 for (var j = 0; j < sz; j++) |
|
114 { |
|
115 var t2 = TEST_TIMESTAMPS[j]; |
|
116 for (var k = 0; k < sz; k++) |
|
117 { |
|
118 var t3 = TEST_TIMESTAMPS[k]; |
|
119 for (var w = 0; w < sz; w++) |
|
120 { |
|
121 var t4 = TEST_TIMESTAMPS[w]; |
|
122 |
|
123 clearDSTOffsetCache(t1); |
|
124 |
|
125 var tzo1 = tzOffsetFromUnixTimestamp(t1); |
|
126 var tzo2 = tzOffsetFromUnixTimestamp(t2); |
|
127 var tzo3 = tzOffsetFromUnixTimestamp(t3); |
|
128 var tzo4 = tzOffsetFromUnixTimestamp(t4); |
|
129 |
|
130 assertEq(tzo1, CORRECT_TZOFFSETS[i]); |
|
131 assertEq(tzo2, CORRECT_TZOFFSETS[j]); |
|
132 assertEq(tzo3, CORRECT_TZOFFSETS[k]); |
|
133 assertEq(tzo4, CORRECT_TZOFFSETS[w]); |
|
134 } |
|
135 } |
|
136 } |
|
137 } |
|
138 } |
|
139 catch (e) |
|
140 { |
|
141 assertEq(true, false, |
|
142 "Error when testing with timestamps " + |
|
143 i + ", " + j + ", " + k + ", " + w + |
|
144 " (" + t1 + ", " + t2 + ", " + t3 + ", " + t4 + ")!"); |
|
145 } |
|
146 |
|
147 reportCompare(true, true); |
|
148 print("All tests passed!"); |
|
149 } |