< prev index next >

jdk/test/java/time/test/java/time/TestClock_System.java

Print this page


   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 }
< prev index next >