1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.util;
18
19import java.io.File;
20import java.io.FileOutputStream;
21import java.io.RandomAccessFile;
22import java.util.TimeZone;
23
24public class ZoneInfoDBTest extends junit.framework.TestCase {
25
26  // The base tzdata file, always present on a device.
27  private static final String TZDATA_IN_ROOT =
28      System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata";
29
30  // An empty override file should fall back to the default file.
31  public void testEmptyOverrideFile() throws Exception {
32    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(TZDATA_IN_ROOT);
33    ZoneInfoDB.TzData dataWithEmptyOverride =
34        new ZoneInfoDB.TzData(makeEmptyFile(), TZDATA_IN_ROOT);
35    assertEquals(data.getVersion(), dataWithEmptyOverride.getVersion());
36    assertEquals(data.getAvailableIDs().length, dataWithEmptyOverride.getAvailableIDs().length);
37  }
38
39  // A corrupt override file should fall back to the default file.
40  public void testCorruptOverrideFile() throws Exception {
41    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(TZDATA_IN_ROOT);
42    ZoneInfoDB.TzData dataWithCorruptOverride =
43        new ZoneInfoDB.TzData(makeCorruptFile(), TZDATA_IN_ROOT);
44    assertEquals(data.getVersion(), dataWithCorruptOverride.getVersion());
45    assertEquals(data.getAvailableIDs().length, dataWithCorruptOverride.getAvailableIDs().length);
46  }
47
48  // Given no tzdata files we can use, we should fall back to built-in "GMT".
49  public void testNoGoodFile() throws Exception {
50    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeEmptyFile());
51    assertEquals("missing", data.getVersion());
52    assertEquals(1, data.getAvailableIDs().length);
53    assertEquals("GMT", data.getAvailableIDs()[0]);
54  }
55
56  // Given a valid override file, we should find ourselves using that.
57  public void testGoodOverrideFile() throws Exception {
58    RandomAccessFile in = new RandomAccessFile(TZDATA_IN_ROOT, "r");
59    byte[] content = new byte[(int) in.length()];
60    in.readFully(content);
61    // Bump the version number to one long past where humans will be extinct.
62    content[6] = '9';
63    content[7] = '9';
64    content[8] = '9';
65    content[9] = '9';
66    content[10] = 'z';
67    in.close();
68
69    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(TZDATA_IN_ROOT);
70    String goodFile = makeTemporaryFile(content);
71    try {
72      ZoneInfoDB.TzData dataWithOverride = new ZoneInfoDB.TzData(goodFile, TZDATA_IN_ROOT);
73      assertEquals("9999z", dataWithOverride.getVersion());
74      assertEquals(data.getAvailableIDs().length, dataWithOverride.getAvailableIDs().length);
75    } finally {
76      new File(goodFile).delete();
77    }
78  }
79
80  // Confirms any caching that exists correctly handles TimeZone mutability.
81  public void testMakeTimeZone_timeZoneMutability() throws Exception {
82    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(TZDATA_IN_ROOT);
83    String tzId = "Europe/London";
84    ZoneInfo first = data.makeTimeZone(tzId);
85    ZoneInfo second = data.makeTimeZone(tzId);
86    assertNotSame(first, second);
87
88    assertTrue(first.hasSameRules(second));
89
90    first.setID("Not Europe/London");
91
92    assertFalse(first.getID().equals(second.getID()));
93
94    first.setRawOffset(3600);
95    assertFalse(first.getRawOffset() == second.getRawOffset());
96  }
97
98  public void testMakeTimeZone_notFound() throws Exception {
99    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(TZDATA_IN_ROOT);
100    assertNull(data.makeTimeZone("THIS_TZ_DOES_NOT_EXIST"));
101    assertFalse(data.hasTimeZone("THIS_TZ_DOES_NOT_EXIST"));
102  }
103
104  public void testMakeTimeZone_found() throws Exception {
105    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(TZDATA_IN_ROOT);
106    assertNotNull(data.makeTimeZone("Europe/London"));
107    assertTrue(data.hasTimeZone("Europe/London"));
108  }
109
110  private static String makeCorruptFile() throws Exception {
111    return makeTemporaryFile("invalid content".getBytes());
112  }
113
114  private static String makeEmptyFile() throws Exception {
115    return makeTemporaryFile(new byte[0]);
116  }
117
118  private static String makeTemporaryFile(byte[] content) throws Exception {
119    File f = File.createTempFile("temp-", ".txt");
120    FileOutputStream fos = new FileOutputStream(f);
121    fos.write(content);
122    fos.close();
123    return f.getPath();
124  }
125}
126