1 /*
   2  * Copyright (c) 2012, 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  */
  23 
  24 /*
  25  *@test
  26  *@bug 8007572 8008161
  27  *@summary Test whether the TimeZone generated from JSR310 tzdb is the same
  28  *as the one from the tz data from javazic
  29  */
  30 
  31 import java.io.File;
  32 import java.lang.reflect.*;
  33 import java.nio.file.*;
  34 import java.util.*;
  35 import java.util.regex.*;
  36 import java.time.zone.*;
  37 import java.time.ZoneId;
  38 
  39 public class TestZoneInfo310 {
  40 
  41     public static void main(String[] args) throws Throwable {
  42 
  43         String TESTDIR = System.getProperty("test.dir", ".");
  44         String SRCDIR = System.getProperty("test.src", ".");
  45         String tzdir = SRCDIR + File.separator + "tzdata";
  46         String tzfiles = "africa antarctica asia australasia europe northamerica pacificnew southamerica backward etcetera systemv";
  47         String jdk_tzdir = SRCDIR + File.separator + "tzdata_jdk";
  48         String jdk_tzfiles = "gmt jdk11_backward";
  49         String zidir = TESTDIR + File.separator + "zi";
  50         File fZidir = new File(zidir);
  51         if (!fZidir.exists()) {
  52             fZidir.mkdirs();
  53         }
  54         Matcher m = Pattern.compile("tzdata(?<ver>[0-9]{4}[A-z])")
  55                            .matcher(new String(Files.readAllBytes(Paths.get(tzdir, "VERSION")), "ascii"));
  56         String ver = m.find() ? m.group("ver") : "NULL";
  57 
  58         ArrayList<String> alist = new ArrayList<>();
  59         alist.add("-V");
  60         alist.add(ver);
  61         alist.add("-d");
  62         alist.add(zidir);
  63         for (String f : tzfiles.split(" ")) {
  64             alist.add(tzdir + File.separator + f);
  65         }
  66         for (String f : jdk_tzfiles.split(" ")) {
  67             alist.add(jdk_tzdir + File.separator + f);
  68         }
  69         System.out.println("Compiling tz files!");
  70         Main.main(alist.toArray(new String[alist.size()]));
  71         //////////////////////////////////
  72 
  73         System.out.println("testing!");
  74         ZoneInfoFile.ziDir = zidir;
  75         long t0, t1;
  76 
  77         t0 = System.nanoTime();
  78         ZoneInfoOld.getTimeZone("America/Los_Angeles");
  79         t1 = System.nanoTime();
  80         System.out.printf("OLD.getZoneInfoOld()[1]=%d%n", (t1 - t0) / 1000);
  81 
  82         t0 = System.nanoTime();
  83         ZoneInfoOld.getTimeZone("America/New_York");
  84         t1 = System.nanoTime();
  85         System.out.printf("OLD.getZoneInfoOld()[2]=%d%n", (t1 - t0) / 1000);
  86 
  87         t0 = System.nanoTime();
  88         ZoneInfoOld.getTimeZone("America/Denver");
  89         t1 = System.nanoTime();
  90         System.out.printf("OLD.getZoneInfoOld()[3]=%d%n", (t1 - t0) / 1000);
  91 
  92         t0 = System.nanoTime();
  93         String[] zids_old = ZoneInfoOld.getAvailableIDs();
  94         t1 = System.nanoTime();
  95         System.out.printf("OLD.getAvailableIDs()=%d, total=%d%n",
  96                           (t1 - t0) / 1000, zids_old.length);
  97         Arrays.sort(zids_old);
  98 
  99         t0 = System.nanoTime();
 100         ZoneId.of("America/Los_Angeles").getRules();
 101         t1 = System.nanoTime();
 102         System.out.printf("NEW.getTimeZone()[1]=%d%n", (t1 - t0) / 1000);
 103 
 104         t0 = System.nanoTime();
 105         TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 106         t1 = System.nanoTime();
 107         System.out.printf("NEW.getTimeZone()[1]=%d%n", (t1 - t0) / 1000);
 108 
 109         t0 = System.nanoTime();
 110         tz = TimeZone.getTimeZone("America/New_York");
 111         t1 = System.nanoTime();
 112         System.out.printf("NEW.getTimeZone()[2]=%d%n", (t1 - t0) / 1000);
 113 
 114         t0 = System.nanoTime();
 115         tz = TimeZone.getTimeZone("America/Denver");
 116         t1 = System.nanoTime();
 117         System.out.printf("NEW.getTimeZone()[3]=%d%n", (t1 - t0) / 1000);
 118 
 119         t0 = System.nanoTime();
 120         String[] zids_new = TimeZone.getAvailableIDs();
 121         t1 = System.nanoTime();
 122         System.out.printf("NEW.getAvailableIDs()=%d, total=%d%n",
 123                           (t1 - t0) / 1000, zids_new.length);
 124         Arrays.sort(zids_new);
 125 
 126         t0 = System.currentTimeMillis();
 127         for (String zid : zids_new) {
 128             TimeZone.getTimeZone(zid);
 129         }
 130         t1 = System.currentTimeMillis();
 131         System.out.printf("NEW.TotalTZ()=%d (ms)%n", t1 - t0);
 132 
 133         t0 = System.currentTimeMillis();
 134         for (String zid : zids_old) {
 135             ZoneInfoOld.getTimeZone(zid);
 136         }
 137         t1 = System.currentTimeMillis();
 138         System.out.printf("OLD.TotalTZ()=%d (ms)%n", t1 - t0);
 139 
 140         if (!Arrays.equals(zids_old, zids_new)) {
 141             throw new RuntimeException("  FAILED:  availableIds don't match");
 142         }
 143         for (String zid : zids_new) {
 144             ZoneInfoOld zi = toZoneInfoOld(TimeZone.getTimeZone(zid));
 145             ZoneInfoOld ziOLD = (ZoneInfoOld)ZoneInfoOld.getTimeZone(zid);
 146             if (! zi.equalsTo(ziOLD)) {
 147                 System.out.println(zi.diffsTo(ziOLD));
 148                 throw new RuntimeException("  FAILED:  " + zid);
 149             }
 150         }
 151         delete(fZidir);
 152 
 153         // test tzdb version
 154         if (!ver.equals(sun.util.calendar.ZoneInfoFile.getVersion())) {
 155             System.out.printf("  FAILED:  ver=%s, expected=%s%n",
 156                               sun.util.calendar.ZoneInfoFile.getVersion(), ver);
 157             throw new RuntimeException("Version test failed");
 158         }
 159 
 160         // test getAvailableIDs(raw);
 161         zids_new = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
 162         //Arrays.sort(zids_new);
 163         zids_old = ZoneInfoOld.getAvailableIDs(-8 * 60 * 60 * 1000);
 164         if (!Arrays.equals(zids_new, zids_old)) {
 165             System.out.println("------------------------");
 166             System.out.println("NEW.getAvailableIDs(-8:00)");
 167             for (String zid : zids_new) {
 168                 System.out.println(zid);
 169             }
 170             System.out.println("------------------------");
 171             System.out.println("OLD.getAvailableIDs(-8:00)");
 172             for (String zid : zids_old) {
 173                 System.out.println(zid);
 174             }
 175             throw new RuntimeException("  FAILED:  availableIds(offset) don't match");
 176         }
 177     }
 178 
 179     private static void delete(File f) {
 180         if (f.isDirectory()) {
 181             for (File f0 : f.listFiles()) {
 182                delete(f0);
 183             }
 184         }
 185         f.delete();
 186      }
 187 
 188     // to access sun.util.calendar.ZoneInfo's private fields
 189     static Class<?> ziClz;
 190     static Field rawOffset;
 191     static Field checksum;
 192     static Field dstSavings;
 193     static Field transitions;
 194     static Field offsets;
 195     static Field simpleTimeZoneParams;
 196     static Field willGMTOffsetChange;
 197     static {
 198         try {
 199             ziClz = Class.forName("sun.util.calendar.ZoneInfo");
 200             rawOffset = ziClz.getDeclaredField("rawOffset");
 201             checksum = ziClz.getDeclaredField("checksum");
 202             dstSavings = ziClz.getDeclaredField("dstSavings");
 203             transitions = ziClz.getDeclaredField("transitions");
 204             offsets = ziClz.getDeclaredField("offsets");
 205             simpleTimeZoneParams = ziClz.getDeclaredField("simpleTimeZoneParams");
 206             willGMTOffsetChange = ziClz.getDeclaredField("willGMTOffsetChange");
 207             rawOffset.setAccessible(true);
 208             checksum.setAccessible(true);
 209             dstSavings.setAccessible(true);
 210             transitions.setAccessible(true);
 211             offsets.setAccessible(true);
 212             simpleTimeZoneParams.setAccessible(true);
 213             willGMTOffsetChange.setAccessible(true);
 214         } catch (Exception x) {
 215             throw new RuntimeException(x);
 216         }
 217     }
 218 
 219     private static ZoneInfoOld toZoneInfoOld(TimeZone tz) throws Exception {
 220         return new ZoneInfoOld(tz.getID(),
 221                                rawOffset.getInt(tz),
 222                                dstSavings.getInt(tz),
 223                                checksum.getInt(tz),
 224                                (long[])transitions.get(tz),
 225                                (int[])offsets.get(tz),
 226                                (int[])simpleTimeZoneParams.get(tz),
 227                                willGMTOffsetChange.getBoolean(tz));
 228     }
 229 
 230 
 231 }