// 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.uniqueclassmembernames;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import com.android.tools.r8.graph.DexField;
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.naming.NamingLens;
import com.android.tools.r8.naming.NamingTestBase;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Timing;
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.function.BiConsumer;
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 UseUniqueMemberNameTest extends NamingTestBase {

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

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

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

    Map<String, BiConsumer<DexItemFactory, NamingLens>> inspections = new HashMap<>();
    inspections.put("uniquemembernames:keep-rules-1.txt", UseUniqueMemberNameTest::test00_rule1);
    inspections.put("uniquemembernames:keep-rules-2.txt", UseUniqueMemberNameTest::test00_rule2);

    return createTests(tests, inspections);
  }

  private static void test00_rule1(DexItemFactory dexItemFactory, NamingLens naming) {
    DexType a = dexItemFactory.createType("Luniquemembernames/ClsA;");
    assertNotEquals("Luniquemembernames/ClsA;", naming.lookupDescriptor(a).toSourceString());

    DexMethod foo = dexItemFactory.createMethod(
        a, dexItemFactory.createProto(dexItemFactory.intType), "foo");
    String foo_renamed = naming.lookupName(foo).toSourceString();
    assertNotEquals("foo", foo_renamed);

    DexType aa = dexItemFactory.createType("Luniquemembernames/AnotherCls;");
    assertNotEquals("Luniquemembernames/AnotherCls;", naming.lookupDescriptor(aa).toSourceString());

    DexMethod another_foo = dexItemFactory.createMethod(
        aa, dexItemFactory.createProto(dexItemFactory.intType), "foo");
    String another_foo_renamed = naming.lookupName(another_foo).toSourceString();
    assertNotEquals("foo", another_foo_renamed);

    // BaseCls#a and AnotherCls#b are kept.
    // Due to BaseCls#a, BaseCls#foo should not be renamed to a.
    // On the other hand, AnotherCls#foo should be renamed to a.
    assertNotEquals(foo_renamed, another_foo_renamed);

    DexType base = dexItemFactory.createType("Luniquemembernames/BaseCls;");
    DexField f2 = dexItemFactory.createField(base, dexItemFactory.doubleType, "f2");
    DexField another_f2 = dexItemFactory.createField(aa, dexItemFactory.intType, "f2");
    // Fields f2's are only fields that are allowed to be renamed. Thus, they would be renamed to
    // the same name as long as R8 is deterministic.
    assertEquals(
        naming.lookupName(f2).toSourceString(),
        naming.lookupName(another_f2).toSourceString());
  }

  // -useuniqueclassmembernames
  private static void test00_rule2(DexItemFactory dexItemFactory, NamingLens naming) {
    DexType a = dexItemFactory.createType("Luniquemembernames/ClsA;");
    assertNotEquals("Luniquemembernames/ClsA;", naming.lookupDescriptor(a).toSourceString());

    DexMethod foo = dexItemFactory.createMethod(
        a, dexItemFactory.createProto(dexItemFactory.intType), "foo");
    String foo_renamed = naming.lookupName(foo).toSourceString();
    assertNotEquals("foo", foo_renamed);

    DexType aa = dexItemFactory.createType("Luniquemembernames/AnotherCls;");
    assertNotEquals("Luniquemembernames/AnotherCls;", naming.lookupDescriptor(aa).toSourceString());

    DexMethod another_foo = dexItemFactory.createMethod(
        aa, dexItemFactory.createProto(dexItemFactory.intType), "foo");
    String another_foo_renamed = naming.lookupName(another_foo).toSourceString();
    assertNotEquals("foo", another_foo_renamed);

    // With -useuniquemembernames, foo() with the same signature should be renamed to the same name.
    assertEquals(foo_renamed, another_foo_renamed);
    // But, those cannot be renamed to c and b, as those are _globally_ reserved.
    assertNotEquals("c", foo_renamed);
    assertNotEquals("c", another_foo_renamed);
    assertNotEquals("b", foo_renamed);
    assertNotEquals("b", another_foo_renamed);

    DexType base = dexItemFactory.createType("Luniquemembernames/BaseCls;");
    DexField f2 = dexItemFactory.createField(base, dexItemFactory.doubleType, "f2");
    DexField another_f2 = dexItemFactory.createField(aa, dexItemFactory.intType, "f2");
    // They should renamed to the same name w/ -useuniqueclassmembernames.
    assertEquals(
        naming.lookupName(f2).toSourceString(),
        naming.lookupName(another_f2).toSourceString());
  }

}
