/*
 * Copyright (C) 2019 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.tests.vendoroverlay;

import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Test the vendor overlay feature. Requires adb remount with OverlayFS.
 */
@RunWith(DeviceJUnit4ClassRunner.class)
public class VendorOverlayHostTest extends BaseHostJUnit4Test {
  boolean wasRoot = false;

  @Before
  public void setup() throws DeviceNotAvailableException {
    wasRoot = getDevice().isAdbRoot();
    if (!wasRoot) {
      Assume.assumeTrue("Test requires root", getDevice().enableAdbRoot());
    }

    Assume.assumeTrue("Skipping vendor overlay test due to lack of necessary OverlayFS support",
        testConditionsMet());

    getDevice().remountSystemWritable();
    // Was OverlayFS used by adb remount? Without it we can't safely re-enable dm-verity.
    Pattern vendorPattern = Pattern.compile("^overlay .+ /vendor$", Pattern.MULTILINE);
    Pattern productPattern = Pattern.compile("^overlay .+ /product$", Pattern.MULTILINE);
    CommandResult result = getDevice().executeShellV2Command("df");
    Assume.assumeTrue("OverlayFS not used for adb remount on /vendor",
        vendorPattern.matcher(result.getStdout()).find());
    Assume.assumeTrue("OverlayFS not used for adb remount on /product",
        productPattern.matcher(result.getStdout()).find());
  }

  private boolean cmdSucceeded(CommandResult result) {
    return result.getStatus() == CommandStatus.SUCCESS;
  }

  private void assumeMkdirSuccess(String dir) throws DeviceNotAvailableException {
    CommandResult result = getDevice().executeShellV2Command("mkdir -p " + dir);
    Assume.assumeTrue("Couldn't create " + dir, cmdSucceeded(result));
  }

  /**
   * Tests that files in the appropriate /product/vendor_overlay dir are overlaid onto /vendor.
   */
  @Test
  public void testVendorOverlay() throws DeviceNotAvailableException {
    String vndkVersion = getDevice().executeShellV2Command("getprop ro.vndk.version").getStdout();

    // Create files and modify policy
    CommandResult result = getDevice().executeShellV2Command(
        "echo '/(product|system/product)/vendor_overlay/" + vndkVersion +
        "/.* u:object_r:vendor_file:s0'" + " >> /system/etc/selinux/plat_file_contexts");
    Assume.assumeTrue("Couldn't modify plat_file_contexts", cmdSucceeded(result));
    assumeMkdirSuccess("/vendor/testdir");
    assumeMkdirSuccess("/vendor/diffcontext");
    assumeMkdirSuccess("/product/vendor_overlay/'" + vndkVersion + "'/testdir");
    result = getDevice().executeShellV2Command(
        "echo overlay > /product/vendor_overlay/'" + vndkVersion + "'/testdir/test");
    Assume.assumeTrue("Couldn't create text file in testdir", cmdSucceeded(result));
    assumeMkdirSuccess("/product/vendor_overlay/'" + vndkVersion + "'/noexist/test");
    assumeMkdirSuccess("/product/vendor_overlay/'" + vndkVersion + "'/diffcontext/test");
    result = getDevice().executeShellV2Command(
        "restorecon -r /product/vendor_overlay/'" + vndkVersion + "'/testdir");
    Assume.assumeTrue("Couldn't write testdir context", cmdSucceeded(result));

    getDevice().reboot();

    // Test that the file was overlaid properly
    result = getDevice().executeShellV2Command("[ $(cat /vendor/testdir/test) = overlay ]");
    Assert.assertTrue("test file was not overlaid onto /vendor/", cmdSucceeded(result));
    result = getDevice().executeShellV2Command("[ ! -d /vendor/noexist/test ]");
    Assert.assertTrue("noexist dir shouldn't exist on /vendor", cmdSucceeded(result));
    result = getDevice().executeShellV2Command("[ ! -d /vendor/diffcontext/test ]");
    Assert.assertTrue("diffcontext dir shouldn't exist on /vendor", cmdSucceeded(result));
  }

  // Duplicate of fs_mgr_overlayfs_valid() logic
  // Requires root
  public boolean testConditionsMet() throws DeviceNotAvailableException {
    if (cmdSucceeded(getDevice().executeShellV2Command(
        "[ -e /sys/module/overlay/parameters/override_creds ]"))) {
      return true;
    }
    if (cmdSucceeded(getDevice().executeShellV2Command("[ ! -e /sys/module/overlay ]"))) {
      return false;
    }
    CommandResult result = getDevice().executeShellV2Command("awk '{ print $3 }' /proc/version");
    Pattern kernelVersionPattern = Pattern.compile("([1-9])[.]([0-9]+).*");
    Matcher kernelVersionMatcher = kernelVersionPattern.matcher(result.getStdout());
    kernelVersionMatcher.find();
    int majorKernelVersion;
    int minorKernelVersion;
    try {
      majorKernelVersion = Integer.parseInt(kernelVersionMatcher.group(1));
      minorKernelVersion = Integer.parseInt(kernelVersionMatcher.group(2));
    } catch (Exception e) {
      return false;
    }
    if (majorKernelVersion < 4) {
      return true;
    }
    if (majorKernelVersion > 4) {
      return false;
    }
    if (minorKernelVersion > 6) {
      return false;
    }
    return true;
  }

  @After
  public void tearDown() throws DeviceNotAvailableException {
    if (getDevice().executeAdbCommand("enable-verity").contains("Now reboot your device")) {
      getDevice().reboot();
    }
    if (!wasRoot) {
      getDevice().disableAdbRoot();
    }
  }
}

