1 /* 2 * Copyright (C) 2020 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 package android.tzdata.mts; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.fail; 20 21 import android.icu.util.VersionInfo; 22 import android.os.Build; 23 import android.util.TimeUtils; 24 25 import org.junit.Test; 26 27 import java.io.File; 28 import java.io.FileInputStream; 29 import java.io.IOException; 30 import java.nio.charset.StandardCharsets; 31 32 /** 33 * Tests concerning version information associated with, or affected by, the time zone data module. 34 * 35 * <p>Generally we don't want to assert anything too specific here (like exact version), since that 36 * would mean more to update every tzdb release. Also, if the module being tested contains an old 37 * version then why wouldn't the tests be just as old too? 38 */ 39 public class TimeZoneVersionTest { 40 41 private static final File TIME_ZONE_MODULE_VERSION_FILE = 42 new File("/apex/com.android.tzdata/etc/tz/tz_version"); 43 44 @Test timeZoneModuleIsCompatibleWithThisRelease()45 public void timeZoneModuleIsCompatibleWithThisRelease() throws Exception { 46 String majorVersion = readMajorFormatVersionFromModuleVersionFile(); 47 48 // Each time a release version of Android is declared, this list needs to be updated to 49 // map the Android release to the time zone format version it uses. 50 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) { 51 assertEquals("003", majorVersion); 52 } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) { 53 assertEquals("004", majorVersion); 54 } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.S) { 55 assertEquals("005", majorVersion); 56 } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.S_V2) { 57 // S_V2 is 5.x, as the format version did not change from S. 58 assertEquals("005", majorVersion); 59 } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU) { 60 assertEquals("006", majorVersion); 61 } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { 62 assertEquals("007", majorVersion); 63 } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.VANILLA_ICE_CREAM) { 64 // The "main" branch is also the staging area for the next Android release that won't 65 // have an Android release constant yet. Instead, we have to infer what the expected tz 66 // data set version should be when the SDK_INT identifies it as the latest Android release 67 // in case it is actually the "main" branch. Below we assume that an increment to ICU is 68 // involved with each release of Android and requires an tz data set version increment. 69 // TODO(b/319103072) A future tzdata module will be installed to a range of Android 70 // releases. This test might beed to be reworked because the ICU version may no longer 71 // imply the tz data set to expect. 72 if (VersionInfo.ICU_VERSION.getMajor() > 75) { 73 // ICU version in V is 75. When we update it in a next release major version 74 // should be updated too. 75 assertEquals("009", majorVersion); 76 } else { 77 assertEquals("008", majorVersion); 78 } 79 } else { 80 // If this fails, a new API level has likely been finalized and can be made 81 // an explicit case. Keep this clause and add an explicit "else if" above. 82 // Consider removing any checks for pre-release devices too if they're not 83 // needed for now. 84 fail("Unhandled SDK_INT version:" + Build.VERSION.SDK_INT); 85 } 86 } 87 88 /** 89 * Confirms that tzdb version information available via published APIs is consistent. 90 */ 91 @Test tzdbVersionIsConsistentAcrossApis()92 public void tzdbVersionIsConsistentAcrossApis() throws Exception { 93 String tzModuleTzdbVersion = readTzDbVersionFromModuleVersionFile(); 94 95 String icu4jTzVersion = android.icu.util.TimeZone.getTZDataVersion(); 96 assertEquals(tzModuleTzdbVersion, icu4jTzVersion); 97 98 assertEquals(tzModuleTzdbVersion, TimeUtils.getTimeZoneDatabaseVersion()); 99 } 100 101 /** 102 * Reads up to {@code maxBytes} bytes from the specified file. The returned array can be 103 * shorter than {@code maxBytes} if the file is shorter. 104 */ readBytes(File file, int maxBytes)105 private static byte[] readBytes(File file, int maxBytes) throws IOException { 106 if (maxBytes <= 0) { 107 throw new IllegalArgumentException("maxBytes ==" + maxBytes); 108 } 109 110 try (FileInputStream in = new FileInputStream(file)) { 111 byte[] max = new byte[maxBytes]; 112 int bytesRead = in.read(max, 0, maxBytes); 113 byte[] toReturn = new byte[bytesRead]; 114 System.arraycopy(max, 0, toReturn, 0, bytesRead); 115 return toReturn; 116 } 117 } 118 readTzDbVersionFromModuleVersionFile()119 private static String readTzDbVersionFromModuleVersionFile() throws IOException { 120 byte[] versionBytes = readBytes(TIME_ZONE_MODULE_VERSION_FILE, 13); 121 assertEquals(13, versionBytes.length); 122 123 String versionString = new String(versionBytes, StandardCharsets.US_ASCII); 124 // Format is: xxx.yyy|zzzzz|...., we want zzzzz 125 String[] dataSetVersionComponents = versionString.split("\\|"); 126 return dataSetVersionComponents[1]; 127 } 128 readMajorFormatVersionFromModuleVersionFile()129 private static String readMajorFormatVersionFromModuleVersionFile() throws IOException { 130 byte[] versionBytes = readBytes(TIME_ZONE_MODULE_VERSION_FILE, 7); 131 assertEquals(7, versionBytes.length); 132 133 String versionString = new String(versionBytes, StandardCharsets.US_ASCII); 134 // Format is: xxx.yyy|zzzz|.... we want xxx 135 String[] dataSetVersionComponents = versionString.split("\\."); 136 return dataSetVersionComponents[0]; 137 } 138 } 139