| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package libcore.tzdata.update; |
| |
| import junit.framework.TestCase; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import libcore.tzdata.update.tools.TzDataBundleBuilder; |
| |
| /** |
| * Tests for {@link libcore.tzdata.update.TzDataBundleInstaller}. |
| */ |
| public class TzDataBundleInstallerTest extends TestCase { |
| |
| private static final File SYSTEM_ZONE_INFO_FILE = new File("/system/usr/share/zoneinfo/tzdata"); |
| |
| private TzDataBundleInstaller installer; |
| private File tempDir; |
| private File testInstallDir; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| tempDir = createDirectory("tempDir"); |
| testInstallDir = createDirectory("testInstall"); |
| installer = new TzDataBundleInstaller("TzDataBundleInstallerTest", testInstallDir); |
| } |
| |
| private static File createDirectory(String prefix) throws IOException { |
| File dir = File.createTempFile(prefix, ""); |
| assertTrue(dir.delete()); |
| assertTrue(dir.mkdir()); |
| return dir; |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| if (testInstallDir.exists()) { |
| FileUtils.deleteRecursive(testInstallDir); |
| } |
| if (tempDir.exists()) { |
| FileUtils.deleteRecursive(tempDir); |
| } |
| super.tearDown(); |
| } |
| |
| /** Tests the first update on a device */ |
| public void testSuccessfulFirstUpdate() throws Exception { |
| ConfigBundle tzData = createValidTzDataBundle("2030a"); |
| |
| assertTrue(install(tzData)); |
| assertTzDataInstalled(tzData); |
| } |
| |
| /** |
| * Tests an update on a device when there is a prior update already applied. |
| */ |
| public void testSuccessfulFollowOnUpdate() throws Exception { |
| ConfigBundle tzData1 = createValidTzDataBundle("2030a"); |
| assertTrue(install(tzData1)); |
| assertTzDataInstalled(tzData1); |
| |
| ConfigBundle tzData2 = createValidTzDataBundle("2030b"); |
| assertTrue(install(tzData2)); |
| assertTzDataInstalled(tzData2); |
| } |
| |
| |
| /** Tests that a bundle with a missing file will not update the content. */ |
| public void testMissingRequiredBundleFile() throws Exception { |
| ConfigBundle installedConfigBundle = createValidTzDataBundle("2030a"); |
| assertTrue(install(installedConfigBundle)); |
| assertTzDataInstalled(installedConfigBundle); |
| |
| ConfigBundle incompleteUpdate = |
| createValidTzDataBundleBuilder("2030b").clearBionicTzData().buildUnvalidated(); |
| assertFalse(install(incompleteUpdate)); |
| assertTzDataInstalled(installedConfigBundle); |
| } |
| |
| /** |
| * Tests that an update will be unpacked even if there is a partial update from a previous run. |
| */ |
| public void testInstallWithWorkingDir() throws Exception { |
| File workingDir = new File(testInstallDir, TzDataBundleInstaller.WORKING_DIR_NAME); |
| assertTrue(workingDir.mkdir()); |
| createFile(new File(workingDir, "myFile")); |
| |
| ConfigBundle tzData = createValidTzDataBundle("2030a"); |
| assertTrue(install(tzData)); |
| assertTzDataInstalled(tzData); |
| } |
| |
| /** |
| * Tests that a bundle with a checksum entry that references a missing file will not update the |
| * content. |
| */ |
| public void testChecksumBundleEntry_fileMissing() throws Exception { |
| ConfigBundle badUpdate = |
| createValidTzDataBundleBuilder("2030b") |
| .addChecksum("/fileDoesNotExist", 1234) |
| .build(); |
| assertFalse(install(badUpdate)); |
| assertNoContentInstalled(); |
| } |
| |
| /** |
| * Tests that a bundle with a checksum entry with a bad checksum will not update the |
| * content. |
| */ |
| public void testChecksumBundleEntry_incorrectChecksum() throws Exception { |
| File fileToChecksum = SYSTEM_ZONE_INFO_FILE; |
| long badChecksum = FileUtils.calculateChecksum(fileToChecksum) + 1; |
| ConfigBundle badUpdate = |
| createValidTzDataBundleBuilder("2030b") |
| .clearChecksumEntries() |
| .addChecksum(fileToChecksum.getPath(), badChecksum) |
| .build(); |
| assertFalse(install(badUpdate)); |
| assertNoContentInstalled(); |
| } |
| |
| private boolean install(ConfigBundle configBundle) throws Exception { |
| return installer.install(configBundle.getBundleBytes()); |
| } |
| |
| private ConfigBundle createValidTzDataBundle(String tzDataVersion) |
| throws IOException { |
| return createValidTzDataBundleBuilder(tzDataVersion).build(); |
| } |
| |
| private TzDataBundleBuilder createValidTzDataBundleBuilder(String tzDataVersion) |
| throws IOException { |
| |
| // The file to include in the installation-time checksum check. |
| File fileToChecksum = SYSTEM_ZONE_INFO_FILE; |
| long checksum = FileUtils.calculateChecksum(fileToChecksum); |
| |
| File bionicTzData = new File(tempDir, "zoneinfo"); |
| createFile(bionicTzData); |
| |
| File icuData = new File(tempDir, "icudata"); |
| createFile(icuData); |
| |
| return new TzDataBundleBuilder() |
| .addChecksum(fileToChecksum.getPath(), checksum) |
| .setTzDataVersion(tzDataVersion) |
| .addBionicTzData(bionicTzData) |
| .addIcuTzData(icuData); |
| } |
| |
| private void assertTzDataInstalled(ConfigBundle expectedTzData) throws Exception { |
| assertTrue(testInstallDir.exists()); |
| |
| File currentTzDataDir = new File(testInstallDir, TzDataBundleInstaller.CURRENT_TZ_DATA_DIR_NAME); |
| assertTrue(currentTzDataDir.exists()); |
| |
| File checksumFile = new File(currentTzDataDir, ConfigBundle.CHECKSUMS_FILE_NAME); |
| assertTrue(checksumFile.exists()); |
| |
| File versionFile = new File(currentTzDataDir, |
| ConfigBundle.TZ_DATA_VERSION_FILE_NAME); |
| assertTrue(versionFile.exists()); |
| |
| File bionicFile = new File(currentTzDataDir, ConfigBundle.ZONEINFO_FILE_NAME); |
| assertTrue(bionicFile.exists()); |
| |
| File icuFile = new File(currentTzDataDir, ConfigBundle.ICU_DATA_FILE_NAME); |
| assertTrue(icuFile.exists()); |
| |
| // Also check no working directory is left lying around. |
| File workingDir = new File(testInstallDir, TzDataBundleInstaller.WORKING_DIR_NAME); |
| assertFalse(workingDir.exists()); |
| } |
| |
| private void assertNoContentInstalled() { |
| File currentTzDataDir = new File(testInstallDir, TzDataBundleInstaller.CURRENT_TZ_DATA_DIR_NAME); |
| assertFalse(currentTzDataDir.exists()); |
| |
| // Also check no working directories are left lying around. |
| File workingDir = new File(testInstallDir, TzDataBundleInstaller.WORKING_DIR_NAME); |
| assertFalse(workingDir.exists()); |
| |
| File oldDataDir = new File(testInstallDir, TzDataBundleInstaller.OLD_TZ_DATA_DIR_NAME); |
| assertFalse(oldDataDir.exists()); |
| } |
| |
| private static void createFile(File file) { |
| try (FileOutputStream fos = new FileOutputStream(file)) { |
| fos.write('a'); |
| } catch (IOException e) { |
| fail(e.getMessage()); |
| } |
| } |
| } |