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

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assume.assumeFalse;

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.ProguardTestBuilder;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ir.optimize.Inliner.Reason;
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.MethodSubject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

class TestClass {
  SomeLogic instance;

  public void create() {
    instance = new SomeLogic(new Object());
  }

  void caller() {
    if (instance.someMethod(new SomeClass()) == null) {
      System.out.println("TestMain#caller");
    }
  }

  public static void main(String[] args) {
    TestClass m = new TestClass();
    m.create();
    m.caller();
  }
}

class SomeLogic {
  Object otherField;

  public SomeLogic(Object o) {
    otherField = o;
  }

  public SomeInterface someMethod(SomeClass list) {
    System.out.println("list is" + ((list == null) ? "" : " not") + " null");
    return null;
  }
}

interface SomeInterface {
  byte foo();
}

@NeverClassInline
class SomeClass implements SomeInterface {
  @Override
  public byte foo() {
    return 0x8;
  }
}

// SomeInterface has a single implementer SomeClass: vertical merging candidate.
// If -keepnames specifies a member whose signature can be changed due to vertical merging, their
// names are not preserved because that rule allows shrinking (and optimization) implicitly.
// According to b/130791310, Proguard (via AGP) still keeps that name, but this reproduction shows
// that both R8 and Proguard ignores -keepnames. It turns out that, as per
// https://android.googlesource.com/platform/sdk/+/master/files/proguard-android-optimize.txt#13
// class merging is disabled for Proguard.
@RunWith(Parameterized.class)
public class B130791310 extends TestBase {
  private static final Class<?> MAIN = TestClass.class;
  private static final List<Class<?>> CLASSES =
      ImmutableList.of(MAIN, SomeLogic.class, SomeInterface.class, SomeClass.class);
  private static final String RULES = StringUtils.lines(
      "-keepnames class **.SomeLogic {",
      "  **.SomeInterface someMethod(**.SomeClass);",
      "}"
  );

  private final boolean enableClassMerging;
  private final boolean onlyForceInlining;

  @Parameterized.Parameters(name = "enable class merging: {0}, only force inlining: {1}")
  public static List<Object[]> data() {
    return buildParameters(BooleanUtils.values(), BooleanUtils.values());
  }

  public B130791310(boolean enableClassMerging, boolean onlyForceInlining) {
    this.enableClassMerging = enableClassMerging;
    this.onlyForceInlining = onlyForceInlining;
  }

  private void inspect(CodeInspector inspector, boolean isR8) {
    ClassSubject holder = inspector.clazz(SomeLogic.class);
    assertThat(holder, isPresent());
    assertThat(holder, not(isRenamed()));
    MethodSubject someMethod = holder.uniqueMethodWithName("someMethod");
    if (isR8) {
      if (onlyForceInlining) {
        assertThat(someMethod, isPresent());
        assertThat(someMethod, not(isRenamed()));
      } else {
        assertThat(someMethod, not(isPresent()));
      }
    } else {
      if (enableClassMerging) {
        // Note that the method is not entirely gone, but merged to the implementer, along with some
        // method signature modification.
        assertThat(someMethod, not(isPresent()));
      } else {
        assertThat(someMethod, isPresent());
        assertThat(someMethod, not(isRenamed()));
      }
    }
  }

  @Test
  public void testProguard() throws Exception {
    assumeFalse(onlyForceInlining);
    ProguardTestBuilder builder =
        testForProguard()
            .addProgramClasses(CLASSES)
            .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
            .addKeepClassAndMembersRules(MAIN)
            .addKeepRules(RULES)
            .addTestingAnnotationsAsProgramClasses();
    if (!enableClassMerging) {
        builder.addKeepRules("-optimizations !class/merging/*");
    }
    builder
        .compile()
        .inspect(inspector -> inspect(inspector, false));
  }

  @Test
  public void testR8() throws Exception {
    R8FullTestBuilder builder =
        testForR8(Backend.DEX)
            .addProgramClasses(CLASSES)
            .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
            .addKeepClassAndMembersRules(MAIN)
            .addKeepRules(RULES)
            .enableNeverClassInliningAnnotations();
    if (!enableClassMerging) {
      builder.addOptionsModification(o -> o.enableVerticalClassMerging = false);
    }
    if (onlyForceInlining) {
      builder.addOptionsModification(
          o -> o.testing.validInliningReasons = ImmutableSet.of(Reason.FORCE));
    }
    builder
        .compile()
        .inspect(inspector -> inspect(inspector, true));
  }
}
