// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;

import static com.android.tools.r8.naming.ClassNameMinifier.getParentPackagePrefix;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class PackageNamingTest extends TestBase {

  private final Path input;
  private final Path keepRulesFile;
  private final ThrowingConsumer<CodeInspector, RuntimeException> inspection;

  @Parameters(name = "test: {0} keep: {1}")
  public static Collection<Object[]> data() {
    List<String> tests = Arrays.asList("naming044", "naming101");
    Map<String, ThrowingConsumer<CodeInspector, RuntimeException>> inspections = new HashMap<>();
    inspections.put("naming044:keep-rules-001.txt", PackageNamingTest::test044_rule001);
    inspections.put("naming044:keep-rules-002.txt", PackageNamingTest::test044_rule002);
    inspections.put("naming044:keep-rules-003.txt", PackageNamingTest::test044_rule003);
    inspections.put("naming044:keep-rules-004.txt", PackageNamingTest::test044_rule004);
    inspections.put("naming044:keep-rules-005.txt", PackageNamingTest::test044_rule005);
    inspections.put("naming101:keep-rules-001.txt", PackageNamingTest::test101_rule001);
    inspections.put("naming101:keep-rules-002.txt", PackageNamingTest::test101_rule002);
    inspections.put("naming101:keep-rules-003.txt", PackageNamingTest::test101_rule003);
    inspections.put("naming101:keep-rules-004.txt", PackageNamingTest::test101_rule004);
    inspections.put("naming101:keep-rules-005.txt", PackageNamingTest::test101_rule005);
    inspections.put("naming101:keep-rules-102.txt", PackageNamingTest::test101_rule102);
    inspections.put("naming101:keep-rules-104.txt", PackageNamingTest::test101_rule104);
    inspections.put("naming101:keep-rules-106.txt", PackageNamingTest::test101_rule106);
    return createTests(tests, inspections);
  }

  public PackageNamingTest(
      String test,
      Path keepRulesFile,
      ThrowingConsumer<CodeInspector, RuntimeException> inspection) {
    this.input = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + test + ".jar");
    this.keepRulesFile = keepRulesFile;
    this.inspection = inspection;
  }

  @Test
  public void packageNamingTest() throws Exception {
    testForR8(Backend.DEX)
        .addProgramFiles(input)
        .addKeepRuleFiles(keepRulesFile)
        .setMinApi(21)
        .compile()
        .inspect(inspection);
  }

  private static final List<String> CLASSES_IN_NAMING044 =
      ImmutableList.of("naming044.A", "naming044.B", "naming044.sub.SubA", "naming044.sub.SubB");

  private static final List<String> CLASSES_IN_NAMING101 =
      ImmutableList.of(
          "naming101.c",
          "naming101.d",
          "naming101.a.a",
          "naming101.a.c",
          "naming101.a.b.c",
          "naming101.b.a'",
          "naming101.b.b");

  private static List<Object[]> createTests(
      List<String> tests,
      Map<String, ThrowingConsumer<CodeInspector, RuntimeException>> inspections) {
    List<Object[]> testCases = new ArrayList<>();
    Set<String> usedInspections = new HashSet<>();
    for (String test : tests) {
      File[] keepFiles =
          new File(ToolHelper.EXAMPLES_DIR + test)
              .listFiles(file -> file.isFile() && file.getName().endsWith(".txt"));
      for (File keepFile : keepFiles) {
        String keepName = keepFile.getName();
        ThrowingConsumer<CodeInspector, RuntimeException> inspection =
            getTestOptionalParameter(inspections, usedInspections, test, keepName);
        if (inspection != null) {
          testCases.add(new Object[] {test, keepFile.toPath(), inspection});
        }
      }
    }
    assert usedInspections.size() == inspections.size();
    return testCases;
  }

  private static <T> T getTestOptionalParameter(
      Map<String, T> specifications, Set<String> usedSpecifications, String test, String keepName) {
    T parameter = specifications.get(test);
    if (parameter == null) {
      parameter = specifications.get(test + ":" + keepName);
      if (parameter != null) {
        usedSpecifications.add(test + ":" + keepName);
      }
    } else {
      usedSpecifications.add(test);
    }
    return parameter;
  }

  private static int countPackageDepth(ClassSubject subject) {
    return CharMatcher.is('.').countIn(subject.getFinalName());
  }

  private static void verifyUniqueNaming(CodeInspector inspector, List<String> klasses) {
    Set<String> renamedNames = Sets.newHashSet();
    for (String klass : klasses) {
      String finalName = inspector.clazz(klass).getFinalName();
      assertFalse(renamedNames.contains(finalName));
      renamedNames.add(finalName);
    }
  }

  // repackageclasses ''
  private static void test044_rule001(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING044);

    // All classes are moved to the top-level package, hence no package separator.
    ClassSubject bClassSubject = inspector.clazz("naming044.B");
    assertFalse(bClassSubject.getFinalName().contains("."));

    // Even classes in a sub-package are moved to the same top-level package.
    assertFalse(inspector.clazz("naming044.sub.SubB").getFinalName().contains("."));

    // Method naming044.B.m would be renamed.
    MethodSubject mMethodSubject = bClassSubject.uniqueMethodWithName("m");
    assertNotEquals("m", mMethodSubject.getMethod().getName().toSourceString());
  }

  // repackageclasses 'p44.x'
  private static void test044_rule002(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING044);

    // All classes are moved to a single package, so they all have the same package prefix.
    assertThat(inspector.clazz("naming044.A").getFinalName(), startsWith("p44.x."));

    ClassSubject bClassSubject = inspector.clazz("naming044.B");
    assertThat(bClassSubject.getFinalName(), startsWith("p44.x."));

    ClassSubject subBClassSubject = inspector.clazz("naming044.sub.SubB");
    assertThat(subBClassSubject.getFinalName(), startsWith("p44.x."));

    // Even classes in a sub-package are moved to the same package.
    assertEquals(
        subBClassSubject.getDexProgramClass().getType().getPackageName(),
        bClassSubject.getDexProgramClass().getType().getPackageName());
  }

  // flattenpackagehierarchy ''
  private static void test044_rule003(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING044);

    // All packages are moved to the top-level package, hence only one package separator.
    ClassSubject b = inspector.clazz("naming044.B");
    ClassSubject bClassSubject = inspector.clazz("naming044.B");
    assertEquals(1, countPackageDepth(bClassSubject));

    // Classes in a sub-package are moved to the top-level as well, but in a different one.
    ClassSubject sub = inspector.clazz("naming044.sub.SubB");
    assertEquals(1, countPackageDepth(sub));
    assertNotEquals(
        sub.getDexProgramClass().getType().getPackageName(),
        b.getDexProgramClass().getType().getPackageName());

    // method naming044.B.m would be renamed.
    MethodSubject mMethodSubject = b.uniqueMethodWithName("m");
    assertNotEquals("m", mMethodSubject.getMethod().getName().toSourceString());
  }

  // flattenpackagehierarchy 'p44.y'
  private static void test044_rule004(CodeInspector inspector) {
    // All packages are moved to a single package.
    ClassSubject a = inspector.clazz("naming044.A");
    assertTrue(a.getFinalName().startsWith("p44.y."));
    // naming004.A -> Lp44/y/a/a;
    assertEquals(3, countPackageDepth(a));

    ClassSubject b = inspector.clazz("naming044.B");
    assertTrue(b.getFinalName().startsWith("p44.y."));
    // naming004.B -> Lp44/y/a/b;
    assertEquals(3, countPackageDepth(b));

    ClassSubject sub = inspector.clazz("naming044.sub.SubB");
    assertTrue(sub.getFinalName().startsWith("p44.y."));
    // naming004.sub.SubB -> Lp44/y/b/b;
    assertEquals(3, countPackageDepth(sub));

    // Classes in a sub-package should be in a different package.
    assertNotEquals(
        sub.getDexProgramClass().getType().getPackageName(),
        b.getDexProgramClass().getType().getPackageName());
  }

  private static void test044_rule005(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING044);

    // All packages are renamed somehow. Need to check package hierarchy is consistent.
    ClassSubject a = inspector.clazz("naming044.A");
    assertEquals(1, countPackageDepth(a));
    ClassSubject b = inspector.clazz("naming044.B");
    assertEquals(1, countPackageDepth(b));
    assertEquals(
        a.getDexProgramClass().getType().getPackageName(),
        b.getDexProgramClass().getType().getPackageName());

    ClassSubject sub_a = inspector.clazz("naming044.sub.SubA");
    assertEquals(1, countPackageDepth(sub_a));
    ClassSubject sub_b = inspector.clazz("naming044.sub.SubB");
    assertEquals(1, countPackageDepth(sub_b));
    assertEquals(
        sub_a.getDexProgramClass().getType().getPackageName(),
        sub_b.getDexProgramClass().getType().getPackageName());

    // Lnaming044.B -> La/c --prefix--> La
    // Lnaming044.sub.SubB -> La/b/b --prefix--> La/b --prefix--> La
    assertEquals(
        getParentPackagePrefix(b.getFinalName()),
        getParentPackagePrefix(getParentPackagePrefix(sub_b.getFinalName())));
  }

  private static void test101_rule001(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING101);

    // All classes are moved to the top-level package, hence no package separator.
    ClassSubject c = inspector.clazz("naming101.c");
    assertFalse(c.getFinalName().contains("."));

    ClassSubject abc = inspector.clazz("naming101.a.b.c");
    assertFalse(abc.getFinalName().contains("."));
    assertNotEquals(abc.getFinalName(), c.getFinalName());
  }

  private static void test101_rule002(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    ClassSubject aa = inspector.clazz("naming101.a.a");
    assertEquals("naming101.a.a", aa.getFinalName());
    ClassSubject ba = inspector.clazz("naming101.b.a");
    assertEquals("naming101.b.a", ba.getFinalName());

    // Repackaged to naming101.a, but naming101.a.a exists to make a name conflict.
    // Thus, everything else should not be renamed to 'a',
    // except for naming101.b.a, which is also kept due to **.a
    List<String> klasses =
        ImmutableList.of(
            "naming101.c", "naming101.d", "naming101.a.c", "naming101.a.b.c", "naming101.b.b");
    for (String klass : klasses) {
      ClassSubject k = inspector.clazz(klass);
      assertEquals("naming101.a", k.getDexProgramClass().getType().getPackageName());
      assertNotEquals("naming101.a.a", k.getFinalName());
    }
  }

  private static void test101_rule003(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING101);

    // All packages are moved to the top-level package, hence only one package separator.
    ClassSubject aa = inspector.clazz("naming101.a.a");
    assertEquals(1, countPackageDepth(aa));

    ClassSubject ba = inspector.clazz("naming101.b.a");
    assertEquals(1, countPackageDepth(ba));

    assertNotEquals(
        aa.getDexProgramClass().getType().getPackageName(),
        ba.getDexProgramClass().getType().getPackageName());
  }

  private static void test101_rule004(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    ClassSubject aa = inspector.clazz("naming101.a.a");
    assertEquals("naming101.a.a", aa.getFinalName());
    ClassSubject ba = inspector.clazz("naming101.b.a");
    assertEquals("naming101.b.a", ba.getFinalName());

    // Flattened to naming101, hence all other classes will be in naming101.* package.
    // Due to naming101.a.a, prefix naming101.a is already used. So, any other classes,
    // except for naming101.a.c, should not have naming101.a as package.
    List<String> klasses =
        ImmutableList.of(
            "naming101.c", "naming101.d", "naming101.a.b.c", "naming101.b.a", "naming101.b.b");
    for (String klass : klasses) {
      ClassSubject k = inspector.clazz(klass);
      assertNotEquals("naming101.a", k.getDexProgramClass().getType().getPackageName());
    }
  }

  private static void test101_rule005(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING101);

    // All packages are renamed somehow. Need to check package hierarchy is consistent.
    ClassSubject aa = inspector.clazz("naming101.a.a");
    assertEquals(1, countPackageDepth(aa));
    ClassSubject abc = inspector.clazz("naming101.a.b.c");
    assertEquals(1, countPackageDepth(abc));

    // naming101.a/a; -> La/a/a; --prefix--> La/a
    // naming101.a/b/c; -> La/a/a/a; --prefix--> La/a/a --prefix--> La/a
    assertEquals(
        getParentPackagePrefix(aa.getFinalName()),
        getParentPackagePrefix(getParentPackagePrefix(abc.getFinalName())));
  }

  private static void test101_rule102(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    ClassSubject aa = inspector.clazz("naming101.a.a");
    assertEquals("naming101.a.a", aa.getFinalName());
    ClassSubject ba = inspector.clazz("naming101.b.a");
    assertEquals("naming101.b.a", ba.getFinalName());
    // Due to package-private access, classes in the same package should remain in the same package.
    ClassSubject ac = inspector.clazz("naming101.a.c");
    assertEquals(
        aa.getDexProgramClass().getType().getPackageName(),
        ac.getDexProgramClass().getType().getPackageName());
    ClassSubject bb = inspector.clazz("naming101.b.b");
    assertEquals(
        ba.getDexProgramClass().getType().getPackageName(),
        bb.getDexProgramClass().getType().getPackageName());

    // We cannot repackage c or d since these have package-private members and a
    // keep,allowobfuscation. For us to be able to repackage them, we have to use
    // -allowaccesmodification.
    List<String> klasses = ImmutableList.of("naming101.c", "naming101.d");
    for (String klass : klasses) {
      ClassSubject k = inspector.clazz(klass);
      assertNotEquals("naming101.a", k.getDexProgramClass().getType().getPackageName());
    }

    // All other classes can be repackaged to naming101.a, but naming101.a.a exists to make a name
    // conflict. Thus, those should not be renamed to 'a'.
    ClassSubject namingAbc = inspector.clazz("naming101.a.b.c");
    assertEquals("naming101.a", namingAbc.getDexProgramClass().getType().getPackageName());
    assertNotEquals("naming101.a.a", namingAbc.getFinalName());
  }

  private static void test101_rule104(CodeInspector inspector) {
    verifyUniqueNaming(inspector, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    ClassSubject aa = inspector.clazz("naming101.a.a");
    assertEquals("naming101.a.a", aa.getFinalName());
    ClassSubject ba = inspector.clazz("naming101.b.a");
    assertEquals("naming101.b.a", ba.getFinalName());
    // Due to package-private access, classes in the same package should remain in the same package.
    ClassSubject ac = inspector.clazz("naming101.a.c");
    assertEquals(
        aa.getDexProgramClass().getType().getPackageName(),
        ac.getDexProgramClass().getType().getPackageName());
    ClassSubject bb = inspector.clazz("naming101.b.b");
    assertEquals(
        ba.getDexProgramClass().getType().getPackageName(),
        bb.getDexProgramClass().getType().getPackageName());

    // All other packages are flattened to naming101, hence all other classes will be in
    // naming101.* package. Due to naming101.a.a, prefix naming101.a is already used. So,
    // remaining classes should not have naming101.a as package.
    List<String> klasses = ImmutableList.of("naming101.c", "naming101.d", "naming101.a.b.c");
    for (String klass : klasses) {
      ClassSubject k = inspector.clazz(klass);
      assertNotEquals("naming101.a", k.getDexProgramClass().getType().getPackageName());
    }
  }

  private static void test101_rule106(CodeInspector inspector) {
    // Classes that end with either c or d will be kept and renamed.
    List<String> klasses =
        CLASSES_IN_NAMING101.stream()
            .filter(className -> className.endsWith("c") || className.endsWith("d"))
            .collect(Collectors.toList());
    verifyUniqueNaming(inspector, klasses);

    // Check naming101.c is kept as-is.
    ClassSubject topC = inspector.clazz("naming101.c");
    assertEquals("naming101.c", topC.getFinalName());

    // naming101.d accesses to a package-private, static field in naming101.c.
    // Therefore, it should remain in the same package.
    ClassSubject topD = inspector.clazz("naming101.d");
    assertEquals("naming101", topD.getDexProgramClass().getType().getPackageName());

    // The remaining classes are in subpackages of naming101 and will therefore not have
    // package-private access to namin101.c
    ClassSubject subAC = inspector.clazz("naming101.a.c");
    assertEquals(1, countPackageDepth(subAC));

    ClassSubject subABC = inspector.clazz("naming101.a.b.c");
    assertEquals(1, countPackageDepth(subABC));
  }
}
