1 /*
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
51 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
52 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
56 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60 package test.java.time;
61
62 import static org.testng.Assert.assertEquals;
63 import static org.testng.Assert.assertSame;
64
65 import java.time.Clock;
66 import java.time.ZoneId;
67
68 import org.testng.annotations.Test;
69
70 /**
71 * Test system clock.
72 */
73 @Test
74 public class TestClock_System {
75
76 private static final ZoneId PARIS = ZoneId.of("Europe/Paris");
77
78 public void test_withZone_same() {
79 Clock test = Clock.system(PARIS);
80 Clock changed = test.withZone(PARIS);
81 assertSame(test, changed);
82 }
83
84 //-----------------------------------------------------------------------
85 public void test_toString() {
86 Clock test = Clock.system(PARIS);
87 assertEquals(test.toString(), "SystemClock[Europe/Paris]");
88 }
89
90 }
|
1 /*
2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
51 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
52 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
56 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60 package test.java.time;
61
62 import static org.testng.Assert.assertEquals;
63 import static org.testng.Assert.assertSame;
64
65 import java.lang.reflect.Field;
66 import java.time.Clock;
67 import java.time.Instant;
68 import java.time.ZoneId;
69
70 import org.testng.annotations.Test;
71
72 /**
73 * Test system clock.
74 */
75 @Test
76 public class TestClock_System {
77
78 private static final ZoneId PARIS = ZoneId.of("Europe/Paris");
79
80 public void test_withZone_same() {
81 Clock test = Clock.system(PARIS);
82 Clock changed = test.withZone(PARIS);
83 assertSame(test, changed);
84 }
85
86 //-----------------------------------------------------------------------
87 public void test_toString() {
88 Clock test = Clock.system(PARIS);
89 assertEquals(test.toString(), "SystemClock[Europe/Paris]");
90 }
91
92 //-----------------------------------------------------------------------
93
94 private static String formatTime(String prefix, Instant time) {
95 return prefix + ": " + time + " - seconds: "
96 + time.getEpochSecond() + ", nanos: "
97 + time.getNano();
98 }
99
100 public void test_ClockResolution() {
101 Clock highestUTC = Clock.systemUTC();
102
103 Instant start = Instant.ofEpochMilli(System.currentTimeMillis());
104
105 try {
106 // smoke test
107 Instant system1 = Instant.ofEpochMilli(System.currentTimeMillis());
108 Instant system2 = Instant.ofEpochMilli(System.currentTimeMillis());
109 Instant highest1 = highestUTC.instant();
110 Instant highest2 = highestUTC.instant();
111 System.out.println(formatTime("\nsystemUTC #1 ", system1));
112 System.out.println(formatTime("systemUTC #2 ", system2));
113 System.out.println(formatTime("highestResolutionUTC #1 ", highest1));
114 System.out.println(formatTime("highestResolutionUTC #2 ", highest2));
115
116 if (system2.isBefore(system1)) {
117 System.err.println("system2 is before system1!");
118 System.err.println(formatTime("\n\tsystem1", system1));
119 System.err.println(formatTime("\n\tsystem2", system2));
120 throw new RuntimeException("system2 is before system1!"
121 + formatTime("\n\tsystem1", system1)
122 + formatTime("\n\tsystem2", system2));
123 }
124 if (highest2.isBefore(highest1)) {
125 System.err.println("highest2 is before highest1!");
126 System.err.println(formatTime("\n\thighest1", system1));
127 System.err.println(formatTime("\n\tsystem2", highest2));
128 throw new RuntimeException("highest2 is before system1!"
129 + formatTime("\n\thighest1", system1)
130 + formatTime("\n\tsystem2", highest2));
131 }
132
133 // better test - but depends on implementation details.
134 // we're not rounding - so highest1 should be greater or equal to
135 // system1
136 system1 = Instant.ofEpochMilli(System.currentTimeMillis());
137 highest1 = highestUTC.instant();
138
139 System.out.println(formatTime("\nsystemUTC ", system1));
140 System.out.println(formatTime("highestResolutionUTC ", highest1));
141
142 if (highest1.isBefore(system1)) {
143 System.err.println("highest1 is before system1!");
144 System.err.println(formatTime("\n\tsystem1", system1));
145 System.err.println(formatTime("\n\thighest1", highest1));
146 throw new RuntimeException("highest1 is before system1!"
147 + formatTime("\n\tsystem1", system1)
148 + formatTime("\n\thighest1", highest1));
149 }
150
151 int count=0;
152 // let's preheat the system a bit:
153 for (int i = 0; i < 1000 ; i++) {
154 system1 = Instant.ofEpochMilli(System.currentTimeMillis());
155 highest1 = highestUTC.instant();
156 final int sysnan = system1.getNano();
157 final int nanos = highest1.getNano();
158 if ((nanos % 1000000) > 0) {
159 count++; // we have micro seconds
160 }
161 if ((sysnan % 1000000) > 0) {
162 throw new RuntimeException("Expected only millisecconds "
163 + "precision for systemUTC, found "
164 + (sysnan % 1000000) + " remainder.");
165 }
166 }
167 System.out.println("\nNumber of time stamps which had better than"
168 + " millisecond precision: "+count+"/"+1000);
169 System.out.println(formatTime("\nsystemUTC ", system1));
170 System.out.println(formatTime("highestResolutionUTC ", highest1));
171 if (count == 0) {
172 System.err.println("Something is strange: no microsecond "
173 + "precision with highestResolutionUTC?");
174 throw new RuntimeException("Micro second preccision not reached");
175 }
176
177 // check again
178 if (highest1.isBefore(system1)) {
179 System.err.println("highest1 is before system1!");
180 System.err.println(formatTime("\n\tsystem1", system1));
181 System.err.println(formatTime("\n\thighest1", highest1));
182 throw new RuntimeException("highest1 is before system1!"
183 + formatTime("\n\tsystem1", system1)
184 + formatTime("\n\thighest1", highest1));
185 }
186
187 // leap of faith: ensure that highest1 is from within 10 secs of
188 // system1
189 if (highest1.toEpochMilli() != system1.toEpochMilli()) {
190 long delta = highest1.getEpochSecond() - system1.getEpochSecond();
191 if (delta > 10) {
192 throw new RuntimeException("Unexpected long delay between two clocks ("
193 + delta + " seconds)"
194 + formatTime("\n\t system1", system1)
195 + formatTime("\n\t highest1", highest1));
196
197 }
198 } else {
199 System.out.println("You won the lottery: the two dates are within 1 millisecond!\n");
200 }
201
202 } finally {
203 Instant stop = Instant.ofEpochMilli(System.currentTimeMillis());
204 if (start.isAfter(stop)) {
205 // This should not happen - but can (un)probably be observed
206 // when switching to summer time, or if another application
207 // is switching the system date...
208 System.err.println("Cannot test - date was setback: "
209 + formatTime("\n\tstarted at", start)
210 + formatTime("\n\tstopped at", stop) + "\n");
211 return; // will prevent exceptions from being propagated.
212 }
213 }
214 }
215
216 static final long MAX_OFFSET = 0x0100000000L;
217 static final long MIN_OFFSET = -MAX_OFFSET;
218
219 // A helper class to test that SystemClock correctly recomputes
220 // its offset.
221 static class SystemClockOffset {
222
223 static final int MILLIS_IN_SECOND = 1000;
224 static final int NANOS_IN_MILLI = 1000_000;
225 static final int NANOS_IN_MICRO = 1000;
226 static final int NANOS_IN_SECOND = 1000_000_000;
227
228 static final boolean verbose = true;
229 static final Clock systemUTC = Clock.systemUTC();
230 static final Field offsetField;
231
232 static {
233 try {
234 offsetField = Class.forName("java.time.Clock$SystemClock").getDeclaredField("offset");
235 offsetField.setAccessible(true);
236 } catch (ClassNotFoundException | NoSuchFieldException ex) {
237 throw new ExceptionInInitializerError(ex);
238 }
239 }
240
241 static enum Answer {
242
243 YES, // isOffLimit = YES: we must get -1
244 NO, // isOffLimit = NO: we must not not get -1
245 MAYBE // isOffLimit = MAYBE: we might get -1 or a valid adjustment.
246 };
247
248 static long distance(long one, long two) {
249 return one > two ? Math.subtractExact(one, two)
250 : Math.subtractExact(two, one);
251 }
252
253 static Answer isOffLimits(long before, long after, long offset) {
254 long relativeDistanceBefore = distance(before, offset);
255 long relativeDistanceAfter = distance(after, offset);
256 if (relativeDistanceBefore >= MAX_OFFSET && relativeDistanceAfter >= MAX_OFFSET) {
257 return Answer.YES;
258 }
259 if (relativeDistanceBefore < MAX_OFFSET && relativeDistanceAfter < MAX_OFFSET) {
260 if (relativeDistanceBefore == 0 || relativeDistanceAfter == 0) {
261 return Answer.MAYBE; // unlucky case where
262 }
263 return Answer.NO;
264 }
265 return Answer.MAYBE;
266 }
267
268 static void testWithOffset(String name, long offset)
269 throws IllegalAccessException {
270 testWithOffset(name, offset, systemUTC);
271 }
272
273 static void testWithOffset(String name, long offset, Clock clock)
274 throws IllegalAccessException {
275 offsetField.set(clock, offset);
276 long beforeMillis = System.currentTimeMillis();
277 final Instant instant = clock.instant();
278 long afterMillis = System.currentTimeMillis();
279 long actualOffset = offsetField.getLong(clock);
280 long instantMillis = instant.getEpochSecond() * MILLIS_IN_SECOND
281 + instant.getNano() / NANOS_IN_MILLI;
282 if (instantMillis < beforeMillis || instantMillis > afterMillis) {
283 throw new RuntimeException(name
284 + ": Invalid instant: " + instant
285 + " (~" + instantMillis + "ms)"
286 + " when time in millis is in ["
287 + beforeMillis + ", " + afterMillis
288 + "] and offset in seconds is " + offset);
289 }
290 Answer isOffLimits = isOffLimits(beforeMillis / MILLIS_IN_SECOND,
291 afterMillis / MILLIS_IN_SECOND, offset);
292 switch (isOffLimits) {
293 case YES:
294 if (actualOffset == offset) {
295 throw new RuntimeException(name
296 + ": offset was offlimit but was not recomputed "
297 + " when time in millis is in ["
298 + beforeMillis + ", " + afterMillis
299 + "] and offset in seconds was " + offset);
300 }
301 break;
302 case NO:
303 if (actualOffset != offset) {
304 throw new RuntimeException(name
305 + ": offset was not offlimit but was recomputed.");
306 }
307 break;
308 default:
309 break;
310 }
311 if (distance(actualOffset, instant.getEpochSecond()) >= MAX_OFFSET) {
312 throw new RuntimeException(name + ": Actual offset is too far off:"
313 + " offset=" + actualOffset
314 + "instant.seconds=" + instant.getEpochSecond());
315 }
316 long adjustment = (instant.getEpochSecond() - actualOffset) * NANOS_IN_SECOND
317 + instant.getNano();
318 validateAdjustment(name, actualOffset, beforeMillis, afterMillis, adjustment);
319 }
320
321 static void validateAdjustment(String name, long offset, long beforeMillis,
322 long afterMillis, long adjustment) {
323 System.out.println("Validating adjustment: " + adjustment);
324 long expectedMax = distance(offset, beforeMillis / MILLIS_IN_SECOND)
325 * NANOS_IN_SECOND
326 + (beforeMillis % MILLIS_IN_SECOND) * NANOS_IN_MILLI
327 + (afterMillis - beforeMillis + 1) * NANOS_IN_MILLI;
328 long absoluteAdjustment = distance(0, adjustment);
329 if (absoluteAdjustment > expectedMax) {
330 long adjSec = absoluteAdjustment / NANOS_IN_SECOND;
331 long adjMil = (absoluteAdjustment % NANOS_IN_SECOND) / NANOS_IN_MILLI;
332 long adjMic = (absoluteAdjustment % NANOS_IN_MILLI) / NANOS_IN_MICRO;
333 long adjNan = (absoluteAdjustment % NANOS_IN_MICRO);
334 long expSec = expectedMax / NANOS_IN_SECOND;
335 long expMil = (expectedMax % NANOS_IN_SECOND) / NANOS_IN_MILLI;
336 long expMic = (expectedMax % NANOS_IN_MILLI) / NANOS_IN_MICRO;
337 long expNan = (expectedMax % NANOS_IN_MICRO);
338 System.err.println("Excessive adjustment: " + adjSec + "s, "
339 + adjMil + "ms, " + adjMic + "mics, " + adjNan + "ns");
340 System.err.println("Epected max: " + expSec + "s, "
341 + expMil + "ms, " + expMic + "mics, " + expNan + "ns");
342
343 throw new RuntimeException(name
344 + ": Excessive adjustment: " + adjustment
345 + " when time in millis is in ["
346 + beforeMillis + ", " + afterMillis
347 + "] and offset in seconds is " + offset);
348 }
349 }
350 }
351
352 public void test_OffsetRegular() throws IllegalAccessException {
353 System.out.println("*** Testing regular cases ***");
354 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000",
355 System.currentTimeMillis()/1000);
356 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - 1024",
357 System.currentTimeMillis()/1000 - 1024);
358 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + 1024",
359 System.currentTimeMillis()/1000 + 1024);
360 }
361
362 public void test_OffsetLimits() throws IllegalAccessException {
363 System.out.println("*** Testing limits ***");
364 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET + 1",
365 System.currentTimeMillis()/1000 - MAX_OFFSET + 1);
366 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET - 1",
367 System.currentTimeMillis()/1000 + MAX_OFFSET - 1);
368 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET",
369 System.currentTimeMillis()/1000 - MAX_OFFSET);
370 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET",
371 System.currentTimeMillis()/1000 + MAX_OFFSET);
372 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET - 1024",
373 System.currentTimeMillis()/1000 - MAX_OFFSET - 1024);
374 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET + 1024",
375 System.currentTimeMillis()/1000 + MAX_OFFSET + 1024);
376 SystemClockOffset.testWithOffset("0", 0);
377 SystemClockOffset.testWithOffset("-1", -1);
378 SystemClockOffset.testWithOffset("Integer.MAX_VALUE + System.currentTimeMillis()/1000",
379 ((long)Integer.MAX_VALUE) + System.currentTimeMillis()/1000);
380 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - Integer.MIN_VALUE",
381 System.currentTimeMillis()/1000 - Integer.MIN_VALUE);
382 SystemClockOffset.testWithOffset("Long.MAX_VALUE", Long.MAX_VALUE);
383 SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - Long.MIN_VALUE",
384 (Long.MIN_VALUE + System.currentTimeMillis()/1000)*-1);
385 }
386 }
|