// Copyright (c) 2021, 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.repackage;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class RepackageFeatureWithSyntheticsTest extends RepackageTestBase {

  public RepackageFeatureWithSyntheticsTest(
      String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
    super(flattenPackageHierarchyOrRepackageClasses, parameters);
  }

  private static final Class<?> FIRST_FOO =
      com.android.tools.r8.repackage.testclasses.repackagefeaturewithsynthetics.first.Foo.class;

  private static final Class<?> FIRST_PKG_PRIVATE =
      com.android.tools.r8.repackage.testclasses.repackagefeaturewithsynthetics.first
          .PkgProtectedMethod.class;

  private static final List<Class<?>> FIRST_CLASSES =
      ImmutableList.of(FIRST_FOO, FIRST_PKG_PRIVATE);

  private static final Class<?> FIRST_FIRST_FOO =
      com.android.tools.r8.repackage.testclasses.repackagefeaturewithsynthetics.first.first.Foo
          .class;

  private static final Class<?> FIRST_FIRST_PKG_PRIVATE =
      com.android.tools.r8.repackage.testclasses.repackagefeaturewithsynthetics.first.first
          .PkgProtectedMethod.class;

  private static final List<Class<?>> FIRST_FIRST_CLASSES =
      ImmutableList.of(FIRST_FIRST_FOO, FIRST_FIRST_PKG_PRIVATE);

  private static List<Class<?>> getTestClasses() {
    return ImmutableList.<Class<?>>builder()
        .addAll(getBaseClasses())
        .add(TestClass.class)
        .add(I.class)
        .build();
  }

  private static List<Class<?>> getBaseClasses() {
    return FIRST_CLASSES;
  }

  private static List<Class<?>> getFeatureClasses() {
    return FIRST_FIRST_CLASSES;
  }

  private static String EXPECTED = StringUtils.lines("first.Foo", "first.first.Foo");

  @Override
  public String getRepackagePackage() {
    return "dest";
  }

  @Test
  public void testReference() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(getTestClasses())
        .addProgramClasses(getFeatureClasses())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED);
  }

  @Test
  public void test() throws Exception {
    assumeTrue("Feature splits require DEX output.", parameters.isDexRuntime());
    R8TestCompileResult compileResult =
        testForR8(parameters.getBackend())
            .addProgramClasses(getTestClasses())
            .addFeatureSplit(getFeatureClasses().toArray(new Class<?>[0]))
            .addKeepMainRule(TestClass.class)
            .addKeepClassAndMembersRules(FIRST_PKG_PRIVATE, FIRST_FIRST_PKG_PRIVATE)
            .addKeepClassAndMembersRules(I.class)
            .addKeepMethodRules(
                Reference.methodFromMethod(TestClass.class.getDeclaredMethod("run", I.class)))
            .addKeepAttributeInnerClassesAndEnclosingMethod()
            .apply(this::configureRepackaging)
            .enableNeverClassInliningAnnotations()
            .setMinApi(parameters.getApiLevel())
            .compile();

    // Each Foo class will give rise to a single lambda.
    int expectedSyntheticsInBase = 1;
    int expectedSyntheticsInFeature = 1;

    // Check that the first.Foo is repackaged but that the pkg private access class is not.
    // The implies that the lambda which is doing a package private access cannot be repackaged.
    // If it is, the access will fail resulting in a runtime exception.
    compileResult.inspect(
        baseInspector -> {
          assertThat(FIRST_FOO, isRepackagedAsExpected(baseInspector, "a"));
          assertThat(FIRST_PKG_PRIVATE, isNotRepackaged(baseInspector));
          assertEquals(
              getTestClasses().size() + expectedSyntheticsInBase,
              baseInspector.allClasses().size());
        },
        featureInspector -> {
          assertThat(FIRST_FIRST_FOO, isRepackagedAsExpected(featureInspector, "b"));
          assertThat(FIRST_FIRST_PKG_PRIVATE, isNotRepackaged(featureInspector));
          assertEquals(
              getFeatureClasses().size() + expectedSyntheticsInFeature,
              featureInspector.allClasses().size());
        });

    compileResult
        .addFeatureSplitsToRunClasspathFiles()
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("first.Foo", "first.first.Foo");
  }

  public interface I {
    void run();
  }

  public static class TestClass {

    // Public kept run method to accept a lambda ensuring desugaring which cannot be optimized out.
    public static void run(I i) {
      i.run();
    }

    public static void main(String[] args) {
      new com.android.tools.r8.repackage.testclasses.repackagefeaturewithsynthetics.first.Foo();
      new com.android.tools.r8.repackage.testclasses.repackagefeaturewithsynthetics.first.first
          .Foo();
    }
  }
}
