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