171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller/*
271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * Copyright (C) 2015 The Android Open Source Project
371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller *
471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * you may not use this file except in compliance with the License.
671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * You may obtain a copy of the License at
771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller *
871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller *
1071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * Unless required by applicable law or agreed to in writing, software
1171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
1271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * See the License for the specific language governing permissions and
1471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * limitations under the License.
1571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller */
1671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerpackage com.android.timezone.distro.installer;
1771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
1871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport com.android.timezone.distro.DistroVersion;
1971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport com.android.timezone.distro.FileUtils;
2071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport com.android.timezone.distro.StagedDistroOperation;
2171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport com.android.timezone.distro.TimeZoneDistro;
2271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport com.android.timezone.distro.tools.TimeZoneDistroBuilder;
2371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
2471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport junit.framework.TestCase;
2571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
2671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.io.ByteArrayOutputStream;
2771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.io.File;
2871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.io.FileOutputStream;
2971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.io.IOException;
3071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.nio.file.FileVisitResult;
3171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.nio.file.FileVisitor;
3271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.nio.file.Files;
3371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.nio.file.Path;
3471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.nio.file.SimpleFileVisitor;
3571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.nio.file.attribute.BasicFileAttributes;
3671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.util.ArrayList;
3771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.util.List;
3871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.util.zip.ZipEntry;
3971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport java.util.zip.ZipOutputStream;
4071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport libcore.io.IoUtils;
4171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport libcore.tzdata.testing.ZoneInfoTestHelper;
4271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
4371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerimport static org.junit.Assert.assertArrayEquals;
4471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
4571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller/**
4671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller * Tests for {@link TimeZoneDistroInstaller}.
4771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller */
4871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fullerpublic class TimeZoneDistroInstallerTest extends TestCase {
4971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
5071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    // OLDER_RULES_VERSION < SYSTEM_RULES_VERSION < NEW_RULES_VERSION < NEWER_RULES_VERSION
5171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static final String OLDER_RULES_VERSION = "2030a";
5271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static final String SYSTEM_RULES_VERSION = "2030b";
5371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static final String NEW_RULES_VERSION = "2030c";
5471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static final String NEWER_RULES_VERSION = "2030d";
5571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
5671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private TimeZoneDistroInstaller installer;
5771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private File tempDir;
5871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private File testInstallDir;
5971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private File testSystemTzDataDir;
6071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
6171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    @Override
6271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void setUp() throws Exception {
6371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        super.setUp();
6471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        tempDir = createUniqueDirectory(null, "tempDir");
6571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        testInstallDir = createSubDirectory(tempDir, "testInstall");
6671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        testSystemTzDataDir =  createSubDirectory(tempDir, "testSystemTzData");
6771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
6871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Create a file to represent the tzdata file in the /system partition of the device.
6971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File testSystemTzDataFile = new File(testSystemTzDataDir, "tzdata");
7071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] systemTzDataBytes = createTzData(SYSTEM_RULES_VERSION);
7171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        createFile(testSystemTzDataFile, systemTzDataBytes);
7271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
7371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        installer = new TimeZoneDistroInstaller(
7471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                "TimeZoneDistroInstallerTest", testSystemTzDataFile, testInstallDir);
7571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
7671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
7771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
7871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Creates a unique temporary directory. rootDir can be null, in which case the directory will
7971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * be created beneath the directory pointed to by the java.io.tmpdir system property.
8071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
8171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static File createUniqueDirectory(File rootDir, String prefix) throws Exception {
8271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File dir = File.createTempFile(prefix, "", rootDir);
8371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(dir.delete());
8471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(dir.mkdir());
8571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        return dir;
8671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
8771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
8871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static File createSubDirectory(File parent, String subDirName) {
8971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File dir = new File(parent, subDirName);
9071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(dir.mkdir());
9171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        return dir;
9271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
9371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
9471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    @Override
9571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void tearDown() throws Exception {
9671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        if (tempDir.exists()) {
9771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            FileUtils.deleteRecursive(tempDir);
9871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        }
9971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        super.tearDown();
10071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
10171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
10271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /** Tests the an update on a device will fail if the /system tzdata file cannot be found. */
10371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_badSystemFile() throws Exception {
10471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File doesNotExist = new File(testSystemTzDataDir, "doesNotExist");
10571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        TimeZoneDistroInstaller brokenSystemInstaller = new TimeZoneDistroInstaller(
10671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                "TimeZoneDistroInstallerTest", doesNotExist, testInstallDir);
10771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
10871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
10971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        try {
11071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            brokenSystemInstaller.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes));
11171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            fail();
11271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        } catch (IOException expected) {}
11371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
11471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
11571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
11671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
11771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
11871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /** Tests the first successful update on a device */
11971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_successfulFirstUpdate() throws Exception {
12071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
12171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
12271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
12371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
12471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes)));
12571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distroBytes);
12671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
12771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
12871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
12971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
13071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests we can install an update the same version as is in /system.
13171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
13271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_successfulFirstUpdate_sameVersionAsSystem()
13371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            throws Exception {
13471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(SYSTEM_RULES_VERSION, 1);
13571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
13671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
13771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes)));
13871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distroBytes);
13971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
14071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
14171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
14271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
14371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests we cannot install an update older than the version in /system.
14471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
14571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_unsuccessfulFirstUpdate_olderVersionThanSystem()
14671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            throws Exception {
14771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(OLDER_RULES_VERSION, 1);
14871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
14971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_RULES_TOO_OLD,
15071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes)));
15171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
15271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
15371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
15471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
15571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
15671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests an update on a device when there is a prior update already staged.
15771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
15871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_successfulFollowOnUpdate_newerVersion()
15971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            throws Exception {
16071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distro1Bytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
16171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
16271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
16371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro1Bytes)));
16471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distro1Bytes);
16571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
16671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distro2Bytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 2);
16771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
16871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
16971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro2Bytes)));
17071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distro2Bytes);
17171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
17271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distro3Bytes = createValidTimeZoneDistroBytes(NEWER_RULES_VERSION, 1);
17371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
17471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
17571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro3Bytes)));
17671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distro3Bytes);
17771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
17871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
17971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
18071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
18171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests an update on a device when there is a prior update already applied, but the follow
18271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * on update is older than in /system.
18371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
18471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_unsuccessfulFollowOnUpdate_olderVersion()
18571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            throws Exception {
18671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distro1Bytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 2);
18771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
18871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
18971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro1Bytes)));
19071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distro1Bytes);
19171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
19271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distro2Bytes = createValidTimeZoneDistroBytes(OLDER_RULES_VERSION, 1);
19371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
19471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_RULES_TOO_OLD,
19571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro2Bytes)));
19671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distro1Bytes);
19771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
19871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
19971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
2005faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    /**
2015faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * Tests staging an update when there's already an uninstall staged still results in a staged
2025faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * install.
2035faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     */
2045faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    public void testStageInstallWithErrorCode_existingStagedUninstall()
2055faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller            throws Exception {
2065faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        byte[] distro1Bytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
2075faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        simulateInstalledDistro(distro1Bytes);
2085faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertInstalledDistro(distro1Bytes);
2095faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
2105faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(TimeZoneDistroInstaller.UNINSTALL_SUCCESS, installer.stageUninstall());
2115faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertDistroUninstallStaged();
2125faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertInstalledDistro(distro1Bytes);
2135faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
2145faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        byte[] distro2Bytes = createValidTimeZoneDistroBytes(NEWER_RULES_VERSION, 1);
2155faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
2165faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
2175faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro2Bytes)));
2185faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertInstalledDistro(distro1Bytes);
2195faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertInstallDistroStaged(distro2Bytes);
2205faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    }
2215faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
22271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /** Tests that a distro with a missing tzdata file will not update the content. */
22371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_missingTzDataFile() throws Exception {
22471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] stagedDistroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
22571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
22671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
22771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(stagedDistroBytes)));
22871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
22971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
23071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] incompleteDistroBytes =
23171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                createValidTimeZoneDistroBuilder(NEWER_RULES_VERSION, 1)
23271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .clearTzDataForTests()
23371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .buildUnvalidatedBytes();
23471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
23571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE,
23671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(incompleteDistroBytes)));
23771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
23871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
23971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
24071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
24171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /** Tests that a distro with a missing ICU file will not update the content. */
24271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_missingIcuFile() throws Exception {
24371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] stagedDistroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
24471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
24571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
24671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(stagedDistroBytes)));
24771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
24871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
24971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] incompleteDistroBytes =
25071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                createValidTimeZoneDistroBuilder(NEWER_RULES_VERSION, 1)
25171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .clearIcuDataForTests()
25271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .buildUnvalidatedBytes();
25371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
25471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE,
25571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(incompleteDistroBytes)));
25671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
25771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
25871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
25971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
26071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /** Tests that a distro with a missing tzlookup file will not update the content. */
26171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_missingTzLookupFile() throws Exception {
26271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] stagedDistroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
26371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
26471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
26571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(stagedDistroBytes)));
26671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
26771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
26871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] incompleteDistroBytes =
26971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                createValidTimeZoneDistroBuilder(NEWER_RULES_VERSION, 1)
27071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .setTzLookupXml(null)
27171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .buildUnvalidatedBytes();
27271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
27371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE,
27471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(incompleteDistroBytes)));
27571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
27671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
27771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
27871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
27971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /** Tests that a distro with a bad tzlookup file will not update the content. */
28071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_badTzLookupFile() throws Exception {
28171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] stagedDistroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
28271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
28371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
28471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(stagedDistroBytes)));
28571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
28671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
28771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] incompleteDistroBytes =
28871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                createValidTimeZoneDistroBuilder(NEWER_RULES_VERSION, 1)
28971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .setTzLookupXml("<foo />")
29071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        .buildUnvalidatedBytes();
29171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
29271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_VALIDATION_ERROR,
29371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(incompleteDistroBytes)));
29471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(stagedDistroBytes);
29571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
29671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
29771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
29871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
29971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests that an update will be unpacked even if there is a partial update from a previous run.
30071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
30171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_withWorkingDir() throws Exception {
30271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File workingDir = installer.getWorkingDir();
30371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(workingDir.mkdir());
30471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        createFile(new File(workingDir, "myFile"), new byte[] { 'a' });
30571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
30671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
30771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
30871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
30971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes)));
31071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distroBytes);
31171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
31271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
31371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
31471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
31571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests that a distro without a distro version file will be rejected.
31671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
31771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_withMissingDistroVersionFile() throws Exception {
31871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Create a distro without a version file.
31971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBuilder(NEW_RULES_VERSION, 1)
32071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .clearVersionForTests()
32171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .buildUnvalidatedBytes();
32271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
32371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE,
32471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes)));
32571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
32671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
32771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
32871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
32971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
33071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests that a distro with an newer distro version will be rejected.
33171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
33271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_withNewerDistroVersion() throws Exception {
33371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Create a distro that will appear to be newer than the one currently supported.
33471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBuilder(NEW_RULES_VERSION, 1)
3353830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller                .replaceFormatVersionForTests(
3363830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller                        DistroVersion.CURRENT_FORMAT_MAJOR_VERSION + 1,
3373830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller                        DistroVersion.CURRENT_FORMAT_MINOR_VERSION)
33871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .buildUnvalidatedBytes();
33971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
34071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_FORMAT_VERSION,
34171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes)));
34271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
34371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
34471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
34571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
34671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
34771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests that a distro with a badly formed distro version will be rejected.
34871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
34971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_withBadlyFormedDistroVersion() throws Exception {
35071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Create a distro that has an invalid major distro version. It should be 3 numeric
35171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // characters, "." and 3 more numeric characters.
3523830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller        byte[] invalidFormatVersionBytes =
3533830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller                createValidTimeZoneDistroBuilder(NEW_RULES_VERSION, 1).buildUnvalidatedBytes();
35471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        invalidFormatVersionBytes[0] = 'A';
35571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
35671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        TimeZoneDistro distro = createTimeZoneDistroWithVersionBytes(invalidFormatVersionBytes);
35771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
35871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE,
35971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(distro));
36071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
36171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
36271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
36371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
36471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
36571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests that a distro with a badly formed revision will be rejected.
36671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
36771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_withBadlyFormedRevision() throws Exception {
36871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Create a distro that has an invalid revision. It should be 3 numeric characters.
3693830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller        byte[] invalidRevisionBytes =
3703830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller                createValidTimeZoneDistroBuilder(NEW_RULES_VERSION, 1).buildUnvalidatedBytes();
37171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        invalidRevisionBytes[invalidRevisionBytes.length - 3] = 'A';
37271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
37371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        TimeZoneDistro distro = createTimeZoneDistroWithVersionBytes(invalidRevisionBytes);
37471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
37571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE,
37671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(distro));
37771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
37871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
37971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
38071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
38171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
38271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Tests that a distro with a badly formed rules version will be rejected.
38371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
38471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageInstallWithErrorCode_withBadlyFormedRulesVersion() throws Exception {
38571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Create a distro that has an invalid rules version. It should be in the form "2016c".
3863830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller        byte[] invalidRulesVersionBytes =
3873830d70bd2373d21e5d7162a2e187d013f1cb090Neil Fuller                createValidTimeZoneDistroBuilder(NEW_RULES_VERSION, 1).buildUnvalidatedBytes();
38871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        invalidRulesVersionBytes[invalidRulesVersionBytes.length - 6] = 'B';
38971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
39071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        TimeZoneDistro distro = createTimeZoneDistroWithVersionBytes(invalidRulesVersionBytes);
39171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
39271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_FAIL_BAD_DISTRO_STRUCTURE,
39371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(distro));
39471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
39571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
39671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
39771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
3985faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    /** Tests what happens if a stageUninstall() is attempted when there's nothing installed. */
39971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageUninstall_noExistingDistro() throws Exception {
40071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // To stage an uninstall, there would need to be installed rules.
4015faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
4025faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED,
4035faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
40471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
40571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
40671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
40771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
40871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
4095faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    /** Tests what happens if a stageUninstall() is attempted when there's something installed. */
4105faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    public void testStageUninstall_existingInstalledDataDistro() throws Exception {
41171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // To stage an uninstall, we need to have some installed rules.
41271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] installedDistroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
41371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        simulateInstalledDistro(installedDistroBytes);
41471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
41571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File stagedDataDir = installer.getStagedTzDataDir();
41671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(stagedDataDir.mkdir());
41771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
4185faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
4195faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_SUCCESS,
4205faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
42171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertDistroUninstallStaged();
42271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstalledDistro(installedDistroBytes);
42371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
42471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
4255faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    /**
4265faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * Tests what happens if a stageUninstall() is attempted when there's something installed
4275faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * and there's a staged install.
4285faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     */
4295faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    public void testStageUninstall_existingStagedInstall() throws Exception {
4305faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        File stagedDataDir = installer.getStagedTzDataDir();
4315faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertTrue(stagedDataDir.mkdir());
4325faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
4335faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        // Stage an install.
4345faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
4355faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(TimeZoneDistroInstaller.INSTALL_SUCCESS,
4365faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distroBytes)));
4375faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
4385faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        // Now uninstall. It should just remove the staged install.
4395faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
4405faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED,
4415faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
4425faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertNoDistroOperationStaged();
4435faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    }
4445faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
4455faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    /**
4465faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * Tests what happens if a stageUninstall() is attempted when there's something installed
4475faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * and there's a staged uninstall.
4485faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     */
4495faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    public void testStageUninstall_existingStagedUninstall() throws Exception {
4505faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        // To stage an uninstall, we need to have some installed rules.
4515faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        byte[] installedDistroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
4525faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        simulateInstalledDistro(installedDistroBytes);
4535faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
4545faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        File stagedDataDir = installer.getStagedTzDataDir();
4555faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertTrue(stagedDataDir.mkdir());
4565faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
4575faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
4585faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_SUCCESS,
4595faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
4605faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertDistroUninstallStaged();
4615faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertInstalledDistro(installedDistroBytes);
4625faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
4635faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        // Now stage a second uninstall.
4645faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
4655faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_SUCCESS,
4665faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
4675faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertDistroUninstallStaged();
4685faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertInstalledDistro(installedDistroBytes);
4695faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    }
4705faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller
4715faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller    /**
4725faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * Tests what happens if a stageUninstall() is attempted when there are unexpected working
4735faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     * directories present.
4745faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller     */
47571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testStageUninstall_oldDirsAlreadyExists() throws Exception {
47671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // To stage an uninstall, we need to have some installed rules.
47771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] installedDistroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
47871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        simulateInstalledDistro(installedDistroBytes);
47971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
48071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File oldStagedDataDir = installer.getOldStagedDataDir();
48171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(oldStagedDataDir.mkdir());
48271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
48371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File workingDir = installer.getWorkingDir();
48471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(workingDir.mkdir());
48571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
4865faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
4875faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_SUCCESS,
4885faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
48971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
49071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertDistroUninstallStaged();
49171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(workingDir.exists());
49271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(oldStagedDataDir.exists());
49371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstalledDistro(installedDistroBytes);
49471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
49571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
49671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testGetSystemRulesVersion() throws Exception {
49771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(SYSTEM_RULES_VERSION, installer.getSystemRulesVersion());
49871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
49971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
50071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testGetInstalledDistroVersion() throws Exception {
50171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check result when nothing installed.
50271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNull(installer.getInstalledDistroVersion());
50371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
50471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
50571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
50671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Now simulate there being an existing install active.
50771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
50871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        simulateInstalledDistro(distroBytes);
50971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstalledDistro(distroBytes);
51071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
51171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check result when something installed.
51271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(new TimeZoneDistro(distroBytes).getDistroVersion(),
51371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.getInstalledDistroVersion());
51471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
51571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstalledDistro(distroBytes);
51671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
51771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
51871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    public void testGetStagedDistroOperation() throws Exception {
51971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distro1Bytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
52071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distro2Bytes = createValidTimeZoneDistroBytes(NEWER_RULES_VERSION, 1);
52171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
52271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check result when nothing staged.
52371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNull(installer.getStagedDistroOperation());
52471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
52571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
52671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
52771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check result after unsuccessfully staging an uninstall.
52871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Can't stage an uninstall without an installed distro.
5295faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
5305faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED,
5315faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
53271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNull(installer.getStagedDistroOperation());
53371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
53471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
53571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
53671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check result after staging an install.
53771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(
53871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                TimeZoneDistroInstaller.INSTALL_SUCCESS,
53971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro1Bytes)));
54071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        StagedDistroOperation expectedStagedInstall =
54171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                StagedDistroOperation.install(new TimeZoneDistro(distro1Bytes).getDistroVersion());
54271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(expectedStagedInstall, installer.getStagedDistroOperation());
54371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distro1Bytes);
54471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
54571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
54671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check result after unsuccessfully staging an uninstall (but after removing a staged
54771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // install). Can't stage an uninstall without an installed distro.
5485faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
5495faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED,
5505faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
55171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNull(installer.getStagedDistroOperation());
55271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoDistroOperationStaged();
55371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNoInstalledDistro();
55471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
55571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Now simulate there being an existing install active.
55671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        simulateInstalledDistro(distro1Bytes);
55771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstalledDistro(distro1Bytes);
55871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
55971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check state after successfully staging an uninstall.
5605faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller        assertEquals(
5615faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                TimeZoneDistroInstaller.UNINSTALL_SUCCESS,
5625faa530d1f732db066aa1bb27943f7db3bb5e7abNeil Fuller                installer.stageUninstall());
56371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        StagedDistroOperation expectedStagedUninstall = StagedDistroOperation.uninstall();
56471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(expectedStagedUninstall, installer.getStagedDistroOperation());
56571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertDistroUninstallStaged();
56671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstalledDistro(distro1Bytes);
56771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
56871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Check state after successfully staging an install.
56971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(TimeZoneDistroInstaller.INSTALL_SUCCESS,
57071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                installer.stageInstallWithErrorCode(new TimeZoneDistro(distro2Bytes)));
57171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        StagedDistroOperation expectedStagedInstall2 =
57271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                StagedDistroOperation.install(new TimeZoneDistro(distro2Bytes).getDistroVersion());
57371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(expectedStagedInstall2, installer.getStagedDistroOperation());
57471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstallDistroStaged(distro2Bytes);
57571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertInstalledDistro(distro1Bytes);
57671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
57771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
57871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static byte[] createValidTimeZoneDistroBytes(
57971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            String rulesVersion, int revision) throws Exception {
58071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        return createValidTimeZoneDistroBuilder(rulesVersion, revision).buildBytes();
58171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
58271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
58371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static TimeZoneDistroBuilder createValidTimeZoneDistroBuilder(
58471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            String rulesVersion, int revision) throws Exception {
58571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
58671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] tzData = createTzData(rulesVersion);
58771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] icuData = new byte[] { 'a' };
588703e2d894aef0491efdbecd93426e52dc064328eNeil Fuller        String tzlookupXml = "<timezones ianaversion=\"" + rulesVersion + "\">\n"
58971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                + "  <countryzones>\n"
590e155631e742d8e791df3a7258e03f27088608e3eNeil Fuller                + "    <country code=\"us\" default=\"America/New_York\" everutc=\"n\">\n"
59140c1a4ffef85c50e8ca0db45a0b121c401285e9dNeil Fuller                + "      <id>America/New_York</id>\n"
59271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                + "      <id>America/Los_Angeles</id>\n"
59371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                + "    </country>\n"
594e155631e742d8e791df3a7258e03f27088608e3eNeil Fuller                + "    <country code=\"gb\" default=\"Europe/London\" everutc=\"y\">\n"
59571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                + "      <id>Europe/London</id>\n"
59671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                + "    </country>\n"
59771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                + "  </countryzones>\n"
59871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                + "</timezones>\n";
59971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        DistroVersion distroVersion = new DistroVersion(
60071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION,
60171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                DistroVersion.CURRENT_FORMAT_MINOR_VERSION,
60271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                rulesVersion,
60371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                revision);
60471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        return new TimeZoneDistroBuilder()
60571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .setDistroVersion(distroVersion)
60671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .setTzDataFile(tzData)
60771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .setIcuDataFile(icuData)
60871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .setTzLookupXml(tzlookupXml);
60971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
61071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
61171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private void assertInstallDistroStaged(byte[] expectedDistroBytes) throws Exception {
61271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(testInstallDir.exists());
61371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
61471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File stagedTzDataDir = installer.getStagedTzDataDir();
61571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(stagedTzDataDir.exists());
61671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
61771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File distroVersionFile =
61871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                new File(stagedTzDataDir, TimeZoneDistro.DISTRO_VERSION_FILE_NAME);
61971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(distroVersionFile.exists());
62071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
62171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File tzdataFile = new File(stagedTzDataDir, TimeZoneDistro.TZDATA_FILE_NAME);
62271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(tzdataFile.exists());
62371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
62471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File icuFile = new File(stagedTzDataDir, TimeZoneDistro.ICU_DATA_FILE_NAME);
62571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(icuFile.exists());
62671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
62771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File tzLookupFile = new File(stagedTzDataDir, TimeZoneDistro.TZLOOKUP_FILE_NAME);
62871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(tzLookupFile.exists());
62971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
63071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Assert getStagedDistroState() is reporting correctly.
63171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        StagedDistroOperation stagedDistroOperation = installer.getStagedDistroOperation();
63271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNotNull(stagedDistroOperation);
63371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(stagedDistroOperation.isUninstall);
63471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(new TimeZoneDistro(expectedDistroBytes).getDistroVersion(),
63571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                stagedDistroOperation.distroVersion);
63671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
63771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File expectedZipContentDir = createUniqueDirectory(tempDir, "expectedZipContent");
63871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        new TimeZoneDistro(expectedDistroBytes).extractTo(expectedZipContentDir);
63971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
64071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertContentsMatches(
64171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                new File(expectedZipContentDir, TimeZoneDistro.DISTRO_VERSION_FILE_NAME),
64271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                distroVersionFile);
64371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertContentsMatches(
64471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                new File(expectedZipContentDir, TimeZoneDistro.ICU_DATA_FILE_NAME),
64571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                icuFile);
64671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertContentsMatches(
64771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                new File(expectedZipContentDir, TimeZoneDistro.TZDATA_FILE_NAME),
64871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                tzdataFile);
64971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertContentsMatches(
65071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                new File(expectedZipContentDir, TimeZoneDistro.TZLOOKUP_FILE_NAME),
65171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                tzLookupFile);
65271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFileCount(4, expectedZipContentDir);
65371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
65471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Also check no working directory is left lying around.
65571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File workingDir = installer.getWorkingDir();
65671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(workingDir.exists());
65771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
65871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
65971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static void assertFileCount(int expectedFiles, File rootDir) throws Exception {
66071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        final List<Path> paths = new ArrayList<>();
66171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
66271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            @Override
66371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs)
66471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        throws IOException {
66571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                paths.add(filePath);
66671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                return FileVisitResult.CONTINUE;
66771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            }
66871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        };
66971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        Files.walkFileTree(rootDir.toPath(), visitor);
67071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals("Found: " + paths, expectedFiles, paths.size());
67171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
67271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
67371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private void assertContentsMatches(File expected, File actual) throws IOException {
67471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] actualBytes = IoUtils.readFileAsByteArray(actual.getPath());
67571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] expectedBytes = IoUtils.readFileAsByteArray(expected.getPath());
67671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertArrayEquals(expectedBytes, actualBytes);
67771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
67871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
67971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private void assertNoDistroOperationStaged() throws Exception {
68071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertNull(installer.getStagedDistroOperation());
68171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
68271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File stagedTzDataDir = installer.getStagedTzDataDir();
68371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(stagedTzDataDir.exists());
68471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
68571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Also check no working directories are left lying around.
68671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File workingDir = installer.getWorkingDir();
68771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(workingDir.exists());
68871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
68971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File oldDataDir = installer.getOldStagedDataDir();
69071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(oldDataDir.exists());
69171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
69271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
69371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private void assertDistroUninstallStaged() throws Exception {
69471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertEquals(StagedDistroOperation.uninstall(), installer.getStagedDistroOperation());
69571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
69671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File stagedTzDataDir = installer.getStagedTzDataDir();
69771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(stagedTzDataDir.exists());
69871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(stagedTzDataDir.isDirectory());
69971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
70071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File uninstallTombstone =
70171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                new File(stagedTzDataDir, TimeZoneDistroInstaller.UNINSTALL_TOMBSTONE_FILE_NAME);
70271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(uninstallTombstone.exists());
70371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(uninstallTombstone.isFile());
70471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
70571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Also check no working directories are left lying around.
70671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File workingDir = installer.getWorkingDir();
70771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(workingDir.exists());
70871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
70971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File oldDataDir = installer.getOldStagedDataDir();
71071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(oldDataDir.exists());
71171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
71271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
71371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private void simulateInstalledDistro(byte[] distroBytes) throws Exception {
71471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File currentTzDataDir = installer.getCurrentTzDataDir();
71571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(currentTzDataDir.exists());
71671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(currentTzDataDir.mkdir());
71771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        new TimeZoneDistro(distroBytes).extractTo(currentTzDataDir);
71871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
71971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
72071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private void assertNoInstalledDistro() {
72171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertFalse(installer.getCurrentTzDataDir().exists());
72271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
72371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
72471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private void assertInstalledDistro(byte[] distroBytes) throws Exception {
72571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File currentTzDataDir = installer.getCurrentTzDataDir();
72671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(currentTzDataDir.exists());
72771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File versionFile = new File(currentTzDataDir, TimeZoneDistro.DISTRO_VERSION_FILE_NAME);
72871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(versionFile.exists());
72971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] expectedVersionBytes = new TimeZoneDistro(distroBytes).getDistroVersion().toBytes();
73071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] actualVersionBytes = FileUtils.readBytes(versionFile, expectedVersionBytes.length);
73171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertArrayEquals(expectedVersionBytes, actualVersionBytes);
73271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
73371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
73471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static byte[] createTzData(String rulesVersion) {
73571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        return new ZoneInfoTestHelper.TzDataBuilder()
73671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .initializeToValid()
73771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .setHeaderMagic("tzdata" + rulesVersion)
73871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                .build();
73971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
74071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
74171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static void createFile(File file, byte[] bytes) {
74271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        try (FileOutputStream fos = new FileOutputStream(file)) {
74371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            fos.write(bytes);
74471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        } catch (IOException e) {
74571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            fail(e.getMessage());
74671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        }
74771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
74871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
74971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    /**
75071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * Creates a TimeZoneDistro containing arbitrary bytes in the version file. Used for testing
75171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     * distros with badly formed version info.
75271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller     */
75371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private TimeZoneDistro createTimeZoneDistroWithVersionBytes(byte[] versionBytes)
75471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            throws Exception {
75571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
75671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Extract a valid distro to a working dir.
75771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        byte[] distroBytes = createValidTimeZoneDistroBytes(NEW_RULES_VERSION, 1);
75871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File workingDir = createUniqueDirectory(tempDir, "versionBytes");
75971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        new TimeZoneDistro(distroBytes).extractTo(workingDir);
76071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
76171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Modify the version file.
76271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        File versionFile = new File(workingDir, TimeZoneDistro.DISTRO_VERSION_FILE_NAME);
76371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        assertTrue(versionFile.exists());
76471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        try (FileOutputStream fos = new FileOutputStream(versionFile, false /* append */)) {
76571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            fos.write(versionBytes);
76671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        }
76771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
76871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        // Zip the distro back up again.
76971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        ByteArrayOutputStream baos = new ByteArrayOutputStream();
77071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        try (ZipOutputStream zos = new ZipOutputStream(baos)) {
77171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            Path workingDirPath = workingDir.toPath();
77271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            Files.walkFileTree(workingDirPath, new SimpleFileVisitor<Path>() {
77371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                @Override
77471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
77571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                        throws IOException {
77671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                    byte[] bytes = IoUtils.readFileAsByteArray(file.toString());
77771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                    String relativeFileName = workingDirPath.relativize(file).toString();
77871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                    addZipEntry(zos, relativeFileName, bytes);
77971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                    return FileVisitResult.CONTINUE;
78071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller                }
78171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            });
78271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        }
78371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
78471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        return new TimeZoneDistro(baos.toByteArray());
78571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
78671a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller
78771a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    private static void addZipEntry(ZipOutputStream zos, String name, byte[] content)
78871a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller            throws IOException {
78971a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        ZipEntry zipEntry = new ZipEntry(name);
79071a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        zipEntry.setSize(content.length);
79171a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        zos.putNextEntry(zipEntry);
79271a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        zos.write(content);
79371a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller        zos.closeEntry();
79471a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller    }
79571a6a6fdb83407ea7a7317e3cdc9128355a5937bNeil Fuller}
796