// 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 com.android.tools.r8.utils.DescriptorUtils.getPackageNameFromDescriptor;
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.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
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 NamingTestBase {

  public PackageNamingTest(
      String test,
      List<String> keepRulesFiles,
      BiConsumer<DexItemFactory, NamingLens> inspection) {
    super(test, keepRulesFiles, inspection, new Timing("PackageNamingTest"));
  }

  @Test
  public void packageNamingTest() throws Exception {
    NamingLens naming = runMinifier(ListUtils.map(keepRulesFiles, Paths::get));
    inspection.accept(dexItemFactory, naming);
  }

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

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

  @Parameters(name = "test: {0} keep: {1}")
  public static Collection<Object[]> data() {
    List<String> tests = Arrays.asList("naming044", "naming101");

    Map<String, BiConsumer<DexItemFactory, NamingLens>> 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);
  }

  private static int countPackageDepth(String descriptor) {
    return CharMatcher.is('/').countIn(descriptor);
  }

  private static void verifyUniqueNaming(
      DexItemFactory dexItemFactory,
      NamingLens naming,
      List<String> klasses) {
    Set<String> renamedNames = Sets.newHashSet();
    for (String klass : klasses) {
      DexType k = dexItemFactory.createType(klass);
      String rename = naming.lookupDescriptor(k).toSourceString();
      assertFalse(renamedNames.contains(rename));
      renamedNames.add(rename);
    }
  }

  // repackageclasses ''
  private static void test044_rule001(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING044);

    // All classes are moved to the top-level package, hence no package separator.
    DexType b = dexItemFactory.createType("Lnaming044/B;");
    assertFalse(naming.lookupDescriptor(b).toSourceString().contains("/"));

    // Even classes in a sub-package are moved to the same top-level package.
    DexType sub = dexItemFactory.createType("Lnaming044/sub/SubB;");
    assertFalse(naming.lookupDescriptor(sub).toSourceString().contains("/"));

    // method naming044.B.m would be renamed.
    DexMethod m = dexItemFactory.createMethod(
        b, dexItemFactory.createProto(dexItemFactory.intType), "m");
    assertNotEquals("m", naming.lookupName(m).toSourceString());
  }

  // repackageclasses 'p44.x'
  private static void test044_rule002(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING044);

    // All classes are moved to a single package, so they all have the same package prefix.
    DexType a = dexItemFactory.createType("Lnaming044/A;");
    assertTrue(naming.lookupDescriptor(a).toSourceString().startsWith("Lp44/x/"));

    DexType b = dexItemFactory.createType("Lnaming044/B;");
    assertTrue(naming.lookupDescriptor(b).toSourceString().startsWith("Lp44/x/"));

    DexType sub = dexItemFactory.createType("Lnaming044/sub/SubB;");
    assertTrue(naming.lookupDescriptor(sub).toSourceString().startsWith("Lp44/x/"));
    // Even classes in a sub-package are moved to the same package.
    assertEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(sub).toSourceString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(b).toSourceString()));
  }

  // flattenpackagehierarchy ''
  private static void test044_rule003(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING044);

    // All packages are moved to the top-level package, hence only one package separator.
    DexType b = dexItemFactory.createType("Lnaming044/B;");
    assertEquals(1, countPackageDepth(naming.lookupDescriptor(b).toSourceString()));

    // Classes in a sub-package are moved to the top-level as well, but in a different one.
    DexType sub = dexItemFactory.createType("Lnaming044/sub/SubB;");
    assertEquals(1, countPackageDepth(naming.lookupDescriptor(sub).toSourceString()));
    assertNotEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(sub).toSourceString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(b).toSourceString()));

    // method naming044.B.m would be renamed.
    DexMethod m = dexItemFactory.createMethod(
        b, dexItemFactory.createProto(dexItemFactory.intType), "m");
    assertNotEquals("m", naming.lookupName(m).toSourceString());
  }

  // flattenpackagehierarchy 'p44.y'
  private static void test044_rule004(DexItemFactory dexItemFactory, NamingLens naming) {
    // All packages are moved to a single package.
    DexType a = dexItemFactory.createType("Lnaming044/A;");
    assertTrue(naming.lookupDescriptor(a).toSourceString().startsWith("Lp44/y/"));
    // naming004.A -> Lp44/y/a/a;
    assertEquals(3, countPackageDepth(naming.lookupDescriptor(a).toSourceString()));

    DexType b = dexItemFactory.createType("Lnaming044/B;");
    assertTrue(naming.lookupDescriptor(b).toSourceString().startsWith("Lp44/y/"));
    // naming004.B -> Lp44/y/a/b;
    assertEquals(3, countPackageDepth(naming.lookupDescriptor(b).toSourceString()));

    DexType sub = dexItemFactory.createType("Lnaming044/sub/SubB;");
    assertTrue(naming.lookupDescriptor(sub).toSourceString().startsWith("Lp44/y/"));
    // naming004.sub.SubB -> Lp44/y/b/b;
    assertEquals(3, countPackageDepth(naming.lookupDescriptor(sub).toSourceString()));

    // Classes in a sub-package should be in a different package.
    assertNotEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(sub).toSourceString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(b).toSourceString()));
  }

  private static void test044_rule005(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING044);

    // All packages are renamed somehow. Need to check package hierarchy is consistent.
    DexType a = dexItemFactory.createType("Lnaming044/A;");
    assertEquals(1, countPackageDepth(naming.lookupDescriptor(a).toSourceString()));
    DexType b = dexItemFactory.createType("Lnaming044/B;");
    assertEquals(1, countPackageDepth(naming.lookupDescriptor(b).toSourceString()));
    assertEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(a).toSourceString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(b).toSourceString()));

    DexType sub_a = dexItemFactory.createType("Lnaming044/sub/SubA;");
    assertEquals(2, countPackageDepth(naming.lookupDescriptor(sub_a).toSourceString()));
    DexType sub_b = dexItemFactory.createType("Lnaming044/sub/SubB;");
    assertEquals(2, countPackageDepth(naming.lookupDescriptor(sub_b).toSourceString()));
    assertEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(sub_a).toSourceString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(sub_b).toSourceString()));

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

  private static void test101_rule001(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING101);

    // All classes are moved to the top-level package, hence no package separator.
    DexType c = dexItemFactory.createType("Lnaming101/c;");
    assertFalse(naming.lookupDescriptor(c).toSourceString().contains("/"));

    DexType abc = dexItemFactory.createType("Lnaming101/a/b/c;");
    assertFalse(naming.lookupDescriptor(abc).toSourceString().contains("/"));
    assertNotEquals(
        naming.lookupDescriptor(abc).toSourceString(),
        naming.lookupDescriptor(c).toSourceString());
  }

  private static void test101_rule002(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
    assertEquals("Lnaming101/a/a;", naming.lookupDescriptor(aa).toSourceString());
    DexType ba = dexItemFactory.createType("Lnaming101/b/a;");
    assertEquals("Lnaming101/b/a;", naming.lookupDescriptor(ba).toSourceString());

    // 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(
        "Lnaming101/c;",
        "Lnaming101/d;",
        "Lnaming101/a/c;",
        "Lnaming101/a/b/c;",
        "Lnaming101/b/b;");
    for (String klass : klasses) {
      DexType k = dexItemFactory.createType(klass);
      String renamedName = naming.lookupDescriptor(k).toSourceString();
      assertEquals("naming101.a", getPackageNameFromDescriptor(renamedName));
      assertNotEquals("Lnaming101/a/a;", renamedName);
    }
  }

  private static void test101_rule003(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING101);

    // All packages are moved to the top-level package, hence only one package separator.
    DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
    assertEquals(1, countPackageDepth(naming.lookupDescriptor(aa).toSourceString()));

    DexType ba = dexItemFactory.createType("Lnaming101/b/a;");
    assertEquals(1, countPackageDepth(naming.lookupDescriptor(ba).toSourceString()));

    assertNotEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(aa).toSourceString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(ba).toSourceString()));
  }

  private static void test101_rule004(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
    assertEquals("Lnaming101/a/a;", naming.lookupDescriptor(aa).toSourceString());
    DexType ba = dexItemFactory.createType("Lnaming101/b/a;");
    assertEquals("Lnaming101/b/a;", naming.lookupDescriptor(ba).toSourceString());

    // 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(
        "Lnaming101/c;",
        "Lnaming101/d;",
        "Lnaming101/a/b/c;",
        "Lnaming101/b/a;",
        "Lnaming101/b/b;");
    for (String klass : klasses) {
      DexType k = dexItemFactory.createType(klass);
      String renamedName = naming.lookupDescriptor(k).toSourceString();
      assertNotEquals("naming101.a", getPackageNameFromDescriptor(renamedName));
    }
  }

  private static void test101_rule005(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING101);

    // All packages are renamed somehow. Need to check package hierarchy is consistent.
    DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
    assertEquals(2, countPackageDepth(naming.lookupDescriptor(aa).toSourceString()));
    DexType abc = dexItemFactory.createType("Lnaming101/a/b/c;");
    assertEquals(3, countPackageDepth(naming.lookupDescriptor(abc).toSourceString()));

    // Lnaming101/a/a; -> La/a/a; --prefix--> La/a
    // Lnaming101/a/b/c; -> La/a/a/a; --prefix--> La/a/a --prefix--> La/a
    assertEquals(
        getParentPackagePrefix(naming.lookupDescriptor(aa).toSourceString()),
        getParentPackagePrefix(
            getParentPackagePrefix(naming.lookupDescriptor(abc).toSourceString())));
  }

  private static void test101_rule102(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
    assertEquals("Lnaming101/a/a;", naming.lookupDescriptor(aa).toSourceString());
    DexType ba = dexItemFactory.createType("Lnaming101/b/a;");
    assertEquals("Lnaming101/b/a;", naming.lookupDescriptor(ba).toSourceString());
    // Due to package-private access, classes in the same package should remain in the same package.
    DexType ac = dexItemFactory.createType("Lnaming101/a/c;");
    assertEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(aa).toString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(ac).toString()));
    DexType bb = dexItemFactory.createType("Lnaming101/b/b;");
    assertEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(ba).toString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(bb).toString()));

    // 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'.
    List<String> klasses = ImmutableList.of(
        "Lnaming101/c;",
        "Lnaming101/d;",
        "Lnaming101/a/b/c;");
    for (String klass : klasses) {
      DexType k = dexItemFactory.createType(klass);
      String renamedName = naming.lookupDescriptor(k).toSourceString();
      assertEquals("naming101.a", getPackageNameFromDescriptor(renamedName));
      assertNotEquals("Lnaming101/a/a;", renamedName);
    }
  }

  private static void test101_rule104(DexItemFactory dexItemFactory, NamingLens naming) {
    verifyUniqueNaming(dexItemFactory, naming, CLASSES_IN_NAMING101);

    // Check naming101.*.a is kept due to **.a
    DexType aa = dexItemFactory.createType("Lnaming101/a/a;");
    assertEquals("Lnaming101/a/a;", naming.lookupDescriptor(aa).toSourceString());
    DexType ba = dexItemFactory.createType("Lnaming101/b/a;");
    assertEquals("Lnaming101/b/a;", naming.lookupDescriptor(ba).toSourceString());
    // Due to package-private access, classes in the same package should remain in the same package.
    DexType ac = dexItemFactory.createType("Lnaming101/a/c;");
    assertEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(aa).toString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(ac).toString()));
    DexType bb = dexItemFactory.createType("Lnaming101/b/b;");
    assertEquals(
        getPackageNameFromDescriptor(naming.lookupDescriptor(ba).toString()),
        getPackageNameFromDescriptor(naming.lookupDescriptor(bb).toString()));

    // 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(
        "Lnaming101/c;",
        "Lnaming101/d;",
        "Lnaming101/a/b/c;");
    for (String klass : klasses) {
      DexType k = dexItemFactory.createType(klass);
      String renamedName = naming.lookupDescriptor(k).toSourceString();
      assertNotEquals("naming101.a", getPackageNameFromDescriptor(renamedName));
    }
  }

  private static void test101_rule106(DexItemFactory dexItemFactory, NamingLens naming) {
    // 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(dexItemFactory, naming, klasses);

    // Check naming101.c is kept as-is.
    DexType topC = dexItemFactory.createType("Lnaming101/c;");
    assertEquals("Lnaming101/c;", naming.lookupDescriptor(topC).toSourceString());

    // naming101.d accesses to a package-private, static field in naming101.c.
    // Therefore, it should remain in the same package.
    DexType topD = dexItemFactory.createType("Lnaming101/d;");
    String renamedTopD = naming.lookupDescriptor(topD).toSourceString();
    assertEquals("naming101", getPackageNameFromDescriptor(renamedTopD));

    // Due to the keep rule for naming101.c, package prefix naming101 is reserved.
    // That is, every renamed class should have naming101 as parent package prefix.
    for (String klass : klasses) {
      DexType t = dexItemFactory.createType(klass);
      String rename = naming.lookupDescriptor(t).toSourceString();
      assertTrue(rename.startsWith("Lnaming101/"));
    }
  }
}
