// Copyright (c) 2019, 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.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assume.assumeFalse;

import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/**
 * Tests that a reserved field name from a given class A is taken into account when renaming the
 * fields in subclasses of A.
 */
@RunWith(Parameterized.class)
public class ReservedFieldNameInSuperClassTest extends TestBase {

  private final boolean reserveName;

  @Parameterized.Parameters(name = "Reserve name: {0}")
  public static Boolean[] data() {
    return BooleanUtils.values();
  }

  public ReservedFieldNameInSuperClassTest(boolean reserveName) {
    this.reserveName = reserveName;
  }

  @Test
  public void testProgramClass() throws Exception {
    String expectedOutput = StringUtils.lines("A.a", "ASub1.foo", "ASub2.bar");
    CodeInspector inspector =
        testForR8(Backend.DEX)
            .addProgramClasses(A.class, ASub1.class, ASub2.class, TestClass.class)
            .addKeepMainRule(TestClass.class)
            .addKeepRules(
                reserveName
                    ? "-keepclassmembernames class " + A.class.getTypeName() + "{ <fields>; }"
                    : "")
            .enableNoHorizontalClassMergingAnnotations()
            .run(TestClass.class)
            .assertSuccessWithOutput(expectedOutput)
            .inspector();

    ClassSubject testClassForFieldSubject = inspector.clazz(A.class);
    assertThat(testClassForFieldSubject, isPresent());

    FieldSubject aFieldSubject = testClassForFieldSubject.uniqueFieldWithOriginalName("a");
    assertThat(aFieldSubject, isPresent());

    // Fields are visited/renamed according to the class hierarchy order. Thus, the field A.a will
    // be visited first and assigned the name a. As it ends up receiving the same name as in the
    // original program, it has not technically been renamed.
    assertThat(aFieldSubject, isPresentAndNotRenamed());

    inspect(inspector);
  }

  @Test
  public void testLibraryClass() throws Exception {
    assumeFalse("No need to add keep rules for the library", reserveName);

    String expectedOutput = StringUtils.lines("A.a", "ASub1.foo", "ASub2.bar");
    testForR8(Backend.DEX)
        .addProgramClasses(ASub1.class, ASub2.class, TestClass.class)
        .addLibraryClasses(A.class)
        .addLibraryFiles(runtimeJar(Backend.DEX))
        .addKeepMainRule(TestClass.class)
        .enableNoHorizontalClassMergingAnnotations()
        .compile()
        .addRunClasspathFiles(testForD8().addProgramClasses(A.class).compile().writeToZip())
        .run(TestClass.class)
        .assertSuccessWithOutput(expectedOutput)
        .inspect(this::inspect);
  }

  private void inspect(CodeInspector inspector) {
    ClassSubject aSub1ClassSubject = inspector.clazz(ASub1.class);
    assertThat(aSub1ClassSubject, isPresent());

    FieldSubject fooFieldSubject = aSub1ClassSubject.uniqueFieldWithOriginalName("foo");
    assertThat(fooFieldSubject, isPresentAndRenamed());
    assertNotEquals("a", fooFieldSubject.getFinalName());

    ClassSubject aSub2ClassSubject = inspector.clazz(ASub2.class);
    assertThat(aSub2ClassSubject, isPresent());

    FieldSubject barFieldSubject = aSub2ClassSubject.uniqueFieldWithOriginalName("bar");
    assertThat(barFieldSubject, isPresentAndRenamed());
    assertNotEquals("a", barFieldSubject.getFinalName());

    // Verify that ASub1.foo and ASub2.bar has been renamed to the same name.
    //
    // Note that this is not a requirement for the correctness of the field name minifier. The field
    // name minifier is in principle free to choose different names for ASub1.foo and ASub2.bar, but
    // this would have a negative impact on code size.
    assertEquals(fooFieldSubject.getFinalName(), barFieldSubject.getFinalName());
  }

  static class A {

    static String a;
  }

  static class ASub1 extends A {

    static String foo;

    ASub1() {
      a = "A.a";
      foo = "ASub1.foo";
    }

    @Override
    public String toString() {
      return a + System.lineSeparator() + foo;
    }
  }

  @NoHorizontalClassMerging
  static class ASub2 extends A {

    static String bar;

    ASub2() {
      bar = "ASub2.bar";
    }

    @Override
    public String toString() {
      return bar;
    }
  }

  static class TestClass {

    public static void main(String[] args) {
      System.out.println(new ASub1());
      System.out.println(new ASub2());
    }
  }
}
