/*
 * Copyright (C) 2017 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 com.android.cts.tzdata;

import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceTestCase;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.StringJoiner;
import java.util.function.Consumer;
import libcore.tzdata.shared2.DistroVersion;
import libcore.tzdata.shared2.TimeZoneDistro;
import libcore.tzdata.testing.ZoneInfoTestHelper;
import libcore.tzdata.update2.tools.TimeZoneDistroBuilder;

import static org.junit.Assert.assertArrayEquals;

/**
 * Tests for the tzdatacheck binary.
 *
 * <p>The tzdatacheck binary operates over two directories: the "system directory" containing the
 * time zone rules in the system image, and a "data directory" in the data partition which can
 * optionally contain time zone rules data files for bionic/libcore and ICU.
 *
 * <p>This test executes the tzdatacheck binary to confirm it operates correctly in a number of
 * simulated situations; simulated system and data directories in various states are created in a
 * location the shell user has permission to access and the tzdatacheck binary is then executed.
 * The status code and directory state after execution is then used to determine if the tzdatacheck
 * binary operated correctly.
 *
 * <p>Most of the tests below prepare simulated directory structure for the system and data dirs
 * on the host before pushing them to the device. Device state is then checked rather than syncing
 * the files back.
 */
public class TzDataCheckTest extends DeviceTestCase {

    /**
     * The name of the directory containing the current time zone rules data beneath
     * {@link #mDataDir}.  Also known to {@link libcore.tzdata.update2.TimeZoneDistroInstaller} and
     * tzdatacheck.cpp.
     */
    private static final String CURRENT_DIR_NAME = "current";

    /**
     * The name of the directory containing the staged time zone rules data beneath
     * {@link #mDataDir}.  Also known to {@link libcore.tzdata.update2.TimeZoneDistroInstaller} and
     * tzdatacheck.cpp.
     */
    private static final String STAGED_DIR_NAME = "staged";

    /**
     * The name of the file inside the staged directory that indicates the staged operation is an
     * uninstall. Also known to {@link libcore.tzdata.update2.TimeZoneDistroInstaller} and
     * tzdatacheck.cpp.
     */
    private static final String UNINSTALL_TOMBSTONE_FILE_NAME = "STAGED_UNINSTALL_TOMBSTONE";

    /**
     * The name of the /system time zone data file. Also known to
     * {@link libcore.tzdata.update2.TimeZoneDistroInstaller} and tzdatacheck.cpp.
     */
    private static final String SYSTEM_TZDATA_FILE_NAME = "tzdata";

    /** A valid time zone rules version guaranteed to be older than {@link #RULES_VERSION_TWO} */
    private static final String RULES_VERSION_ONE = "2016g";
    /** A valid time zone rules version guaranteed to be newer than {@link #RULES_VERSION_ONE} */
    private static final String RULES_VERSION_TWO = "2016h";
    /**
     * An arbitrary, valid time zone rules version used when it doesn't matter what the rules
     * version is.
     */
    private static final String VALID_RULES_VERSION = RULES_VERSION_ONE;

    /** An arbitrary valid revision number. */
    private static final int VALID_REVISION = 1;

    private String mDeviceAndroidRootDir;
    private PathPair mTestRootDir;
    private PathPair mSystemDir;
    private PathPair mDataDir;

    public void setUp() throws Exception {
        super.setUp();

        // It's not clear how we would get this without invoking "/system/bin/sh", but we need the
        // value first to do so. It has been hardcoded instead.
        mDeviceAndroidRootDir = "/system";

        // Create a test root directory on host and device.
        Path hostTestRootDir = Files.createTempDirectory("tzdatacheck_test");
        mTestRootDir = new PathPair(
                hostTestRootDir,
                "/data/local/tmp/tzdatacheck_test");
        createDeviceDirectory(mTestRootDir);

        // tzdatacheck requires two directories: a "system" path and a "data" path.
        mSystemDir = mTestRootDir.createSubPath("system_dir");
        mDataDir = mTestRootDir.createSubPath("data_dir");

        // Create the host-side directory structure (for preparing files before pushing them to
        // device and looking at files retrieved from device).
        createHostDirectory(mSystemDir);
        createHostDirectory(mDataDir);

        // Create the equivalent device-side directory structure for receiving files.
        createDeviceDirectory(mSystemDir);
        createDeviceDirectory(mDataDir);
    }

    @Override
    public void tearDown() throws Exception {
        // Remove the test root directories that have been created by this test.
        deleteHostDirectory(mTestRootDir, true /* failOnError */);
        deleteDeviceDirectory(mTestRootDir, true /* failOnError */);
        super.tearDown();
    }

    public void testTooFewArgs() throws Exception {
        // No need to set up or push files to the device for this test.
        assertEquals(1, runTzDataCheckWithArgs(new String[0]));
        assertEquals(1, runTzDataCheckWithArgs(new String[] { "oneArg" }));
    }

    // {dataDir}/staged exists but it is a file.
    public void testStaging_stagingDirIsFile() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        // Create a file with the same name as the directory that tzdatacheck expects.
        Files.write(dataStagedDir.hostPath, new byte[] { 'a' });

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code. Failures due to staging issues are
        // generally ignored providing the device is left in a reasonable state.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the file was just ignored. This is a fairly arbitrary choice to leave it rather
        // than delete.
        assertDevicePathExists(dataStagedDir);
        assertDevicePathIsFile(dataStagedDir);
    }

    // {dataDir}/staged exists but /current dir is a file.
    public void testStaging_uninstall_currentDirIsFile() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.

        // Create a staged uninstall.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        createStagedUninstallOnHost(dataStagedDir);

        // Create a file with the same name as the directory that tzdatacheck expects.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        Files.write(dataCurrentDir.hostPath, new byte[] { 'a' });

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the device was left in a valid "uninstalled" state.
        assertDevicePathDoesNotExist(dataStagedDir);
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/staged contains an uninstall, but there is nothing to uninstall.
    public void testStaging_uninstall_noCurrent() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);

        // Set up the /data directory structure on host.

        // Create a staged uninstall.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        createStagedUninstallOnHost(dataStagedDir);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code. Failures due to staging issues are
        // generally ignored providing the device is left in a reasonable state.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the device was left in a valid "uninstalled" state.
        assertDevicePathDoesNotExist(dataStagedDir);
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/staged contains an uninstall, and there is something to uninstall.
    public void testStaging_uninstall_withCurrent() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.

        // Create a staged uninstall.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        createStagedUninstallOnHost(dataStagedDir);

        // Create a current installed distro.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        TimeZoneDistro distro = createValidDistroBuilder().build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code. Failures due to staging issues are
        // generally ignored providing the device is left in a reasonable state.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the device was left in a valid "uninstalled" state.
        assertDevicePathDoesNotExist(dataStagedDir);
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/staged exists but /current dir is a file.
    public void testStaging_install_currentDirIsFile() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.

        // Create a staged install.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        TimeZoneDistro distro = createValidDistroBuilder().build();
        unpackOnHost(dataStagedDir, distro);

        // Create a file with the same name as the directory that tzdatacheck expects.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        Files.write(dataCurrentDir.hostPath, new byte[] { 'a' });

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code. Failures due to staging issues are
        // generally ignored providing the device is left in a reasonable state.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the device was left in a valid "installed" state.
        assertDevicePathDoesNotExist(dataStagedDir);
        assertDeviceDirContainsDistro(dataCurrentDir, distro);
    }

    // {dataDir}/staged contains an install, but there is nothing to replace.
    public void testStaging_install_noCurrent() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);

        // Set up the /data directory structure on host.

        // Create a staged install.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        TimeZoneDistro stagedDistro = createValidDistroBuilder().build();
        unpackOnHost(dataStagedDir, stagedDistro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code. Failures due to staging issues are
        // generally ignored providing the device is left in a reasonable state.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the device was left in a valid "installed" state.
        assertDevicePathDoesNotExist(dataStagedDir);
        assertDeviceDirContainsDistro(dataCurrentDir, stagedDistro);
    }

    // {dataDir}/staged contains an install, and there is something to replace.
    public void testStaging_install_withCurrent() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        DistroVersion currentDistroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION, 1, VALID_RULES_VERSION, 1);
        DistroVersion stagedDistroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION, 1, VALID_RULES_VERSION, 2);

        // Set up the /data directory structure on host.

        // Create a staged uninstall.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        TimeZoneDistro stagedDistro = createValidDistroBuilder()
                .setDistroVersion(stagedDistroVersion)
                .build();
        unpackOnHost(dataStagedDir, stagedDistro);

        // Create a current installed distro.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        TimeZoneDistro currentDistro = createValidDistroBuilder()
                .setDistroVersion(currentDistroVersion)
                .build();
        unpackOnHost(dataCurrentDir, currentDistro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code. Failures due to staging issues are
        // generally ignored providing the device is left in a reasonable state.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the device was left in a valid "installed" state.
        // The stagedDistro should now be the one in the current dir.
        assertDevicePathDoesNotExist(dataStagedDir);
        assertDeviceDirContainsDistro(dataCurrentDir, stagedDistro);
    }

    // {dataDir}/staged contains an invalid install, and there is something to replace.
    // Most of the invalid cases are tested without staging; this is just to prove that staging
    // an invalid distro is handled the same.
    public void testStaging_install_withCurrent_invalidStaged() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.

        // Create a staged uninstall which contains invalid.
        PathPair dataStagedDir = mDataDir.createSubPath(STAGED_DIR_NAME);
        TimeZoneDistro stagedDistro = createValidDistroBuilder()
                .clearVersionForTests()
                .buildUnvalidated();
        unpackOnHost(dataStagedDir, stagedDistro);

        // Create a current installed distro.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        TimeZoneDistro currentDistro = createValidDistroBuilder().build();
        unpackOnHost(dataCurrentDir, currentDistro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code. The staged directory will have become the
        // current one, but then it will be discovered to be invalid and will be removed.
        assertEquals(3, runTzDataCheckOnDevice());

        // Assert the device was left in a valid "uninstalled" state.
        assertDevicePathDoesNotExist(dataStagedDir);
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // No {dataDir}/current exists.
    public void testNoCurrentDataDir() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Deliberately not creating anything on host in the data dir here, leaving the empty
        // structure.

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(0, runTzDataCheckOnDevice());
    }

    // {dataDir}/current exists but it is a file.
    public void testCurrentDataDirIsFile() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        // Create a file with the same name as the directory that tzdatacheck expects.
        Files.write(dataCurrentDir.hostPath, new byte[] { 'a' });

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(2, runTzDataCheckOnDevice());

        // Assert the file was just ignored. This is a fairly arbitrary choice to leave it rather
        // than delete.
        assertDevicePathExists(dataCurrentDir);
        assertDevicePathIsFile(dataCurrentDir);
    }

    // {dataDir}/current exists but is missing the distro version file.
    public void testMissingDataDirDistroVersionFile() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        TimeZoneDistro distroWithoutAVersionFile = createValidDistroBuilder()
                .clearVersionForTests()
                .buildUnvalidated();
        unpackOnHost(dataCurrentDir, distroWithoutAVersionFile);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(3, runTzDataCheckOnDevice());

        // Assert the current data directory was deleted.
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/current exists but the distro version file is short.
    public void testShortDataDirDistroVersionFile() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        unpackOnHost(dataCurrentDir, createValidDistroBuilder().build());
        // Replace the distro version file with a short file.
        Path distroVersionFile =
                dataCurrentDir.hostPath.resolve(TimeZoneDistro.DISTRO_VERSION_FILE_NAME);
        assertHostFileExists(distroVersionFile);
        Files.write(distroVersionFile, new byte[3]);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(3, runTzDataCheckOnDevice());

        // Assert the current data directory was deleted.
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/current exists and the distro version file is long enough, but contains junk.
    public void testCorruptDistroVersionFile() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        unpackOnHost(dataCurrentDir, createValidDistroBuilder().build());

        // Replace the distro version file with junk.
        Path distroVersionFile =
                dataCurrentDir.hostPath.resolve(TimeZoneDistro.DISTRO_VERSION_FILE_NAME);
        assertHostFileExists(distroVersionFile);

        int fileLength = (int) Files.size(distroVersionFile);
        byte[] junkArray = new byte[fileLength]; // all zeros
        Files.write(distroVersionFile, junkArray);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(4, runTzDataCheckOnDevice());

        // Assert the current data directory was deleted.
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/current exists but the distro version is incorrect.
    public void testInvalidMajorDistroVersion_older() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        DistroVersion oldMajorDistroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION - 1, 1, VALID_RULES_VERSION, 1);
        TimeZoneDistro distro = createValidDistroBuilder()
                .setDistroVersion(oldMajorDistroVersion)
                .build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(5, runTzDataCheckOnDevice());

        // Assert the current data directory was deleted.
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/current exists but the distro version is incorrect.
    public void testInvalidMajorDistroVersion_newer() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        DistroVersion newMajorDistroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION + 1,
                DistroVersion.CURRENT_FORMAT_MINOR_VERSION,
                VALID_RULES_VERSION, VALID_REVISION);
        TimeZoneDistro distro = createValidDistroBuilder()
                .setDistroVersion(newMajorDistroVersion)
                .build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(5, runTzDataCheckOnDevice());

        // Assert the current data directory was deleted.
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/current exists but the distro version is incorrect.
    public void testInvalidMinorDistroVersion_older() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        DistroVersion oldMinorDistroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION,
                DistroVersion.CURRENT_FORMAT_MINOR_VERSION - 1,
                VALID_RULES_VERSION, 1);
        TimeZoneDistro distro = createValidDistroBuilder()
                .setDistroVersion(oldMinorDistroVersion)
                .build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(5, runTzDataCheckOnDevice());

        // Assert the current data directory was deleted.
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    // {dataDir}/current exists but the distro version is newer (which is accepted because it should
    // be backwards compatible).
    public void testValidMinorDistroVersion_newer() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(VALID_RULES_VERSION);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        DistroVersion newMajorDistroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION,
                DistroVersion.CURRENT_FORMAT_MINOR_VERSION + 1,
                VALID_RULES_VERSION, VALID_REVISION);
        TimeZoneDistro distro = createValidDistroBuilder()
                .setDistroVersion(newMajorDistroVersion)
                .build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the current data directory was not touched.
        assertDeviceDirContainsDistro(dataCurrentDir, distro);
    }

    // {dataDir}/current is valid but the tzdata file in /system is missing.
    public void testSystemTzDataFileMissing() throws Exception {
        // Deliberately not writing anything in /system here.

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        TimeZoneDistro validDistro = createValidDistroBuilder().build();
        unpackOnHost(dataCurrentDir, validDistro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(6, runTzDataCheckOnDevice());

        // Assert the current data directory was not touched.
        assertDeviceDirContainsDistro(dataCurrentDir, validDistro);
    }

    // {dataDir}/current is valid but the tzdata file in /system has an invalid header.
    public void testSystemTzDataFileCorrupt() throws Exception {
        // Set up the /system directory structure on host.
        byte[] invalidTzDataBytes = new byte[20];
        Files.write(mSystemDir.hostPath.resolve(SYSTEM_TZDATA_FILE_NAME), invalidTzDataBytes);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        TimeZoneDistro validDistro = createValidDistroBuilder().build();
        unpackOnHost(dataCurrentDir, validDistro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(7, runTzDataCheckOnDevice());

        // Assert the current data directory was not touched.
        assertDeviceDirContainsDistro(dataCurrentDir, validDistro);
    }

    // {dataDir}/current is valid and the tzdata file in /system is older.
    public void testSystemTzRulesOlder() throws Exception {
        // Set up the /system directory structure on host.
        createSystemTzDataFileOnHost(RULES_VERSION_ONE);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        // Newer than RULES_VERSION_ONE in /system
        final String distroRulesVersion = RULES_VERSION_TWO;
        DistroVersion distroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION,
                DistroVersion.CURRENT_FORMAT_MINOR_VERSION, distroRulesVersion, VALID_REVISION);
        TimeZoneDistro distro = createValidDistroBuilder()
                .setDistroVersion(distroVersion)
                .setTzDataFile(createValidTzDataBytes(distroRulesVersion))
                .build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the current data directory was not touched.
        assertDeviceDirContainsDistro(dataCurrentDir, distro);
    }

    // {dataDir}/current is valid and the tzdata file in /system is the same (and should be kept).
    public void testSystemTzDataSame() throws Exception {
        // Set up the /system directory structure on host.
        final String systemRulesVersion = VALID_RULES_VERSION;
        createSystemTzDataFileOnHost(systemRulesVersion);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        DistroVersion distroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION,
                DistroVersion.CURRENT_FORMAT_MINOR_VERSION, systemRulesVersion, VALID_REVISION);
        TimeZoneDistro distro = createValidDistroBuilder()
                .setDistroVersion(distroVersion)
                .setTzDataFile(createValidTzDataBytes(systemRulesVersion))
                .build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(0, runTzDataCheckOnDevice());

        // Assert the current data directory was not touched.
        assertDeviceDirContainsDistro(dataCurrentDir, distro);
    }

    // {dataDir}/current is valid and the tzdata file in /system is the newer.
    public void testSystemTzDataNewer() throws Exception {
        // Set up the /system directory structure on host.
        String systemRulesVersion = RULES_VERSION_TWO;
        createSystemTzDataFileOnHost(systemRulesVersion);

        // Set up the /data directory structure on host.
        PathPair dataCurrentDir = mDataDir.createSubPath(CURRENT_DIR_NAME);
        String distroRulesVersion = RULES_VERSION_ONE; // Older than the system version.
        DistroVersion distroVersion = new DistroVersion(
                DistroVersion.CURRENT_FORMAT_MAJOR_VERSION,
                DistroVersion.CURRENT_FORMAT_MINOR_VERSION,
                distroRulesVersion,
                VALID_REVISION);
        TimeZoneDistro distro = createValidDistroBuilder()
                .setDistroVersion(distroVersion)
                .setTzDataFile(createValidTzDataBytes(distroRulesVersion))
                .build();
        unpackOnHost(dataCurrentDir, distro);

        // Push the host test directory and contents to the device.
        pushHostTestDirToDevice();

        // Execute tzdatacheck and check the status code.
        assertEquals(0, runTzDataCheckOnDevice());

        // It is important the dataCurrentDir is deleted in this case - this test case is the main
        // reason tzdatacheck exists.
        assertDevicePathDoesNotExist(dataCurrentDir);
    }

    private void createSystemTzDataFileOnHost(String systemRulesVersion) throws IOException {
        byte[] systemTzData = createValidTzDataBytes(systemRulesVersion);
        Files.write(mSystemDir.hostPath.resolve(SYSTEM_TZDATA_FILE_NAME), systemTzData);
    }

    private static void createStagedUninstallOnHost(PathPair stagedDir) throws Exception {
        createHostDirectory(stagedDir);

        PathPair uninstallTombstoneFile = stagedDir.createSubPath(UNINSTALL_TOMBSTONE_FILE_NAME);
        // Create an empty file.
        new FileOutputStream(uninstallTombstoneFile.hostFile()).close();
    }

    private static void unpackOnHost(PathPair path, TimeZoneDistro distro) throws Exception {
        createHostDirectory(path);
        distro.extractTo(path.hostFile());
    }

    private static TimeZoneDistroBuilder createValidDistroBuilder() throws Exception {
        String distroRulesVersion = VALID_RULES_VERSION;
        DistroVersion validDistroVersion =
                new DistroVersion(
                        DistroVersion.CURRENT_FORMAT_MAJOR_VERSION,
                        DistroVersion.CURRENT_FORMAT_MINOR_VERSION,
                        distroRulesVersion, VALID_REVISION);
        return new TimeZoneDistroBuilder()
                .setDistroVersion(validDistroVersion)
                .setTzDataFile(createValidTzDataBytes(distroRulesVersion))
                .setIcuDataFile(new byte[10]);
    }

    private static byte[] createValidTzDataBytes(String rulesVersion) {
        return new ZoneInfoTestHelper.TzDataBuilder()
                .initializeToValid()
                .setHeaderMagic("tzdata" + rulesVersion)
                .build();
    }

    private int runTzDataCheckOnDevice() throws Exception {
        return runTzDataCheckWithArgs(new String[] { mSystemDir.devicePath, mDataDir.devicePath });
    }

    private int runTzDataCheckWithArgs(String[] args) throws Exception {
        String command = createTzDataCheckCommand(mDeviceAndroidRootDir, args);
        return executeCommandOnDeviceWithResultCode(command).statusCode;
    }

    private static String createTzDataCheckCommand(String rootDir, String[] args) {
        StringJoiner joiner = new StringJoiner(" ");
        String tzDataCheckCommand = rootDir + "/bin/tzdatacheck";
        joiner.add(tzDataCheckCommand);
        for (String arg : args) {
            joiner.add(arg);
        }
        return joiner.toString();
    }

    private static void assertHostFileExists(Path path) {
        assertTrue(Files.exists(path));
    }

    private String executeCommandOnDeviceRaw(String command) throws DeviceNotAvailableException {
        return getDevice().executeShellCommand(command);
    }

    private void createDeviceDirectory(PathPair dir) throws DeviceNotAvailableException {
        executeCommandOnDeviceRaw("mkdir -p " + dir.devicePath);
    }

    private static void createHostDirectory(PathPair dir) throws Exception {
        Files.createDirectory(dir.hostPath);
    }

    private static class ShellResult {
        final String output;
        final int statusCode;

        private ShellResult(String output, int statusCode) {
            this.output = output;
            this.statusCode = statusCode;
        }
    }

    private ShellResult executeCommandOnDeviceWithResultCode(String command) throws Exception {
        // A file to hold the script we're going to create.
        PathPair scriptFile = mTestRootDir.createSubPath("script.sh");
        // A file to hold the output of the script.
        PathPair scriptOut = mTestRootDir.createSubPath("script.out");

        // The content of the script. Runs the command, capturing stdout and stderr to scriptOut
        // and printing the result code.
        String hostScriptContent = command + " > " + scriptOut.devicePath + " 2>&1 ; echo -n $?";

        // Parse and return the result.
        try {
            Files.write(scriptFile.hostPath, hostScriptContent.getBytes(StandardCharsets.US_ASCII));

            // Push the script to the device.
            pushFile(scriptFile);

            // Execute the script using "sh".
            String execCommandUnderShell =
                    mDeviceAndroidRootDir + "/bin/sh " + scriptFile.devicePath;
            String resultCodeString = executeCommandOnDeviceRaw(execCommandUnderShell);

            // Pull back scriptOut to the host and read the content.
            pullFile(scriptOut);
            byte[] outputBytes = Files.readAllBytes(scriptOut.hostPath);
            String output = new String(outputBytes, StandardCharsets.US_ASCII);

            int resultCode;
            try {
                resultCode = Integer.parseInt(resultCodeString);
            } catch (NumberFormatException e) {
                fail("Command: " + command
                        + " returned a non-integer: \"" + resultCodeString + "\""
                        + ", output=\"" + output + "\"");
                return null;
            }
            return new ShellResult(output, resultCode);
        } finally {
            deleteDeviceFile(scriptFile, false /* failOnError */);
            deleteDeviceFile(scriptOut, false /* failOnError */);
            deleteHostFile(scriptFile, false /* failOnError */);
            deleteHostFile(scriptOut, false /* failOnError */);
        }
    }

    private void pushHostTestDirToDevice() throws Exception {
        assertTrue(getDevice().pushDir(mTestRootDir.hostFile(), mTestRootDir.devicePath));
    }

    private void pullFile(PathPair file) throws DeviceNotAvailableException {
        assertTrue("Could not pull file " + file.devicePath + " to " + file.hostFile(),
                getDevice().pullFile(file.devicePath, file.hostFile()));
    }

    private void pushFile(PathPair file) throws DeviceNotAvailableException {
        assertTrue("Could not push file " + file.hostFile() + " to " + file.devicePath,
                getDevice().pushFile(file.hostFile(), file.devicePath));
    }

    private void deleteHostFile(PathPair file, boolean failOnError) {
        try {
            Files.deleteIfExists(file.hostPath);
        } catch (IOException e) {
            if (failOnError) {
                fail(e);
            }
        }
    }

    private void deleteDeviceDirectory(PathPair dir, boolean failOnError)
            throws DeviceNotAvailableException {
        String deviceDir = dir.devicePath;
        try {
            executeCommandOnDeviceRaw("rm -r " + deviceDir);
        } catch (Exception e) {
            if (failOnError) {
                throw deviceFail(e);
            }
        }
    }

    private void deleteDeviceFile(PathPair file, boolean failOnError)
            throws DeviceNotAvailableException {
        try {
            assertDevicePathIsFile(file);
            executeCommandOnDeviceRaw("rm " + file.devicePath);
        } catch (Exception e) {
            if (failOnError) {
                throw deviceFail(e);
            }
        }
    }

    private static void deleteHostDirectory(PathPair dir, final boolean failOnError) {
        Path hostPath = dir.hostPath;
        if (Files.exists(hostPath)) {
            Consumer<Path> pathConsumer = file -> {
                try {
                    Files.delete(file);
                } catch (Exception e) {
                    if (failOnError) {
                        fail(e);
                    }
                }
            };

            try {
                Files.walk(hostPath).sorted(Comparator.reverseOrder()).forEach(pathConsumer);
            } catch (IOException e) {
                fail(e);
            }
        }
    }

    private void assertDevicePathExists(PathPair path) throws DeviceNotAvailableException {
        assertTrue(getDevice().doesFileExist(path.devicePath));
    }

    private void assertDeviceDirContainsDistro(PathPair distroPath, TimeZoneDistro expectedDistro)
            throws Exception {
        // Pull back just the version file and compare it.
        File localFile = mTestRootDir.createSubPath("temp.file").hostFile();
        try {
            String remoteVersionFile = distroPath.devicePath + "/"
                    + TimeZoneDistro.DISTRO_VERSION_FILE_NAME;
            assertTrue("Could not pull file " + remoteVersionFile + " to " + localFile,
                    getDevice().pullFile(remoteVersionFile, localFile));

            byte[] bytes = Files.readAllBytes(localFile.toPath());
            assertArrayEquals(bytes, expectedDistro.getDistroVersion().toBytes());
        } finally {
            localFile.delete();
        }
    }

    private void assertDevicePathDoesNotExist(PathPair path) throws DeviceNotAvailableException {
        assertFalse(getDevice().doesFileExist(path.devicePath));
    }

    private void assertDevicePathIsFile(PathPair path) throws DeviceNotAvailableException {
        // This check cannot rely on getDevice().getFile(devicePath).isDirectory() here because that
        // requires that the user has rights to list all files beneath each and every directory in
        // the path. That is not the case for the shell user and the /data and /data/local
        // directories. http://b/35753041.
        String output = executeCommandOnDeviceRaw("stat -c %F " + path.devicePath);
        assertTrue(path.devicePath + " not a file. Received: " + output,
                output.startsWith("regular") && output.endsWith("file\n"));
    }

    private static DeviceNotAvailableException deviceFail(Exception e)
            throws DeviceNotAvailableException {
        if (e instanceof DeviceNotAvailableException) {
            throw (DeviceNotAvailableException) e;
        }
        fail(e);
        return null;
    }

    private static void fail(Exception e) {
        e.printStackTrace();
        fail(e.getMessage());
    }

    /** A path that has equivalents on both host and device. */
    private static class PathPair {
        private final Path hostPath;
        private final String devicePath;

        PathPair(Path hostPath, String devicePath) {
            this.hostPath = hostPath;
            this.devicePath = devicePath;
        }

        File hostFile() {
            return hostPath.toFile();
        }

        PathPair createSubPath(String s) {
            return new PathPair(hostPath.resolve(s), devicePath + "/" + s);
        }
    }
}
