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

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.FieldAccessInstructionSubject;
import com.android.tools.r8.utils.DexInspector.InstructionSubject;
import com.android.tools.r8.utils.DexInspector.InvokeInstructionSubject;
import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.android.tools.r8.utils.TestDescriptionWatcher;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class MemberRebindingTest {

  private static final List<Path> JAR_LIBRARIES = ImmutableList.of(
      ToolHelper.getDefaultAndroidJar(),
      Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "memberrebindinglib.jar"));

  private enum Frontend {
    DEX, JAR;

    @Override
    public String toString() {
      return this == DEX ? ".dex" : ".jar";
    }
  }

  private final Frontend kind;
  private final Path originalDex;
  private final Path programFile;
  private final Consumer<DexInspector> inspection;
  private final Consumer<DexInspector> originalInspection;
  private final int minApiLevel;

  @Rule
  public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();

  @Rule
  public TestDescriptionWatcher watcher = new TestDescriptionWatcher();

  public MemberRebindingTest(TestConfiguration configuration) {
    this.kind = configuration.kind;
    originalDex = configuration.getDexPath();
    if (kind == Frontend.DEX) {
      this.programFile = originalDex;
    } else {
      this.programFile = configuration.getJarPath();
    }
    this.inspection = configuration.processedInspection;
    this.originalInspection = configuration.originalInspection;
    this.minApiLevel = configuration.getMinApiLevel();
  }

  @Before
  public void runR8() throws Exception {
    // Generate R8 processed version without library option.
    String out = temp.getRoot().getCanonicalPath();
    // NOTE: It is important to turn off inlining to ensure
    // dex inspection of invokes is predictable.
    R8Command.Builder builder = R8Command.builder()
        .setOutput(Paths.get(out), OutputMode.DexIndexed)
        .addLibraryFiles(JAR_LIBRARIES)
        .setMinApiLevel(minApiLevel);
    ToolHelper.getAppBuilder(builder).addProgramFiles(programFile);
    ToolHelper.runR8(builder.build(), options -> options.enableInlining = false);
  }

  private static boolean coolInvokes(InstructionSubject instruction) {
    if (!instruction.isInvokeVirtual() && !instruction.isInvokeInterface() &&
        !instruction.isInvokeStatic()) {
      return false;
    }
    InvokeInstructionSubject invoke = (InvokeInstructionSubject) instruction;
    return !invoke.holder().is("java.io.PrintStream");
  }

  private static void inspectOriginalMain(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding.Memberrebinding")
        .method(DexInspector.MAIN);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(MemberRebindingTest::coolInvokes);
    assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsOtherLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebindinglib.AnIndependentInterface"));
    assertTrue(
        iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
    assertTrue(
        iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
    assertFalse(iterator.hasNext());
  }

  private static void inspectMain(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding.Memberrebinding")
        .method(DexInspector.MAIN);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(MemberRebindingTest::coolInvokes);
    assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassInMiddleOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding.SuperClassOfAll"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
    assertTrue(iterator.next().holder().is("memberrebinding.ClassExtendsLibraryClass"));
    // For the next three - test that we re-bind to library methods (holder is java.util.ArrayList).
    assertTrue(iterator.next().holder().is("java.util.ArrayList"));
    assertTrue(iterator.next().holder().is("java.util.ArrayList"));
    assertTrue(iterator.next().holder().is("java.util.ArrayList"));
    assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClassInTheMiddle"));
    assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClassInTheMiddle"));
    // For the next three - test that we re-bind to the lowest library class.
    assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
    assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
    assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
    // The next one is already precise.
    assertTrue(
        iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
    // Some dispatches on interfaces.
    assertTrue(iterator.next().holder().is("memberrebindinglib.AnIndependentInterface"));
    assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
    assertTrue(iterator.next().holder().is("memberrebindinglib.ImplementedInProgramClass"));
    assertFalse(iterator.hasNext());
  }

  private static void inspectOriginalMain2(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding2.Memberrebinding")
        .method(DexInspector.MAIN);
    Iterator<FieldAccessInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isFieldAccess);
    // Run through instance put, static put, instance get and instance get.
    for (int i = 0; i < 4; i++) {
      assertTrue(iterator.next().holder().is("memberrebinding2.ClassAtBottomOfChain"));
      assertTrue(iterator.next().holder().is("memberrebinding2.ClassAtBottomOfChain"));
      assertTrue(iterator.next().holder().is("memberrebinding2.ClassAtBottomOfChain"));
      assertTrue(iterator.next().holder().is("memberrebinding2.subpackage.PublicClass"));
    }
    assertTrue(iterator.next().holder().is("java.lang.System"));
    assertFalse(iterator.hasNext());
  }

  private static void inspectMain2(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding2.Memberrebinding")
        .method(DexInspector.MAIN);
    Iterator<FieldAccessInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isFieldAccess);
    // Run through instance put, static put, instance get and instance get.
    for (int i = 0; i < 4; i++) {
      assertTrue(iterator.next().holder().is("memberrebinding2.ClassAtBottomOfChain"));
      assertTrue(iterator.next().holder().is("memberrebinding2.ClassInMiddleOfChain"));
      assertTrue(iterator.next().holder().is("memberrebinding2.SuperClassOfAll"));
      assertTrue(iterator.next().holder().is("memberrebinding2.subpackage.PublicClass"));
    }
    assertTrue(iterator.next().holder().is("java.lang.System"));
    assertFalse(iterator.hasNext());
  }

  public static MethodSignature TEST =
      new MethodSignature("test", "void", new String[]{});

  private static void inspectOriginal3(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding3.Memberrebinding").method(TEST);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isInvoke);
    assertTrue(iterator.next().holder().is("memberrebinding3.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding3.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding3.ClassAtBottomOfChain"));
    assertFalse(iterator.hasNext());
  }

  private static void inspect3(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding3.Memberrebinding").method(TEST);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isInvoke);
    assertTrue(iterator.next().holder().is("memberrebinding3.ClassAtBottomOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding3.ClassInMiddleOfChain"));
    assertTrue(iterator.next().holder().is("memberrebinding3.SuperClassOfAll"));
    assertFalse(iterator.hasNext());
  }

  private static void inspectOriginal4(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding4.Memberrebinding").method(TEST);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isInvoke);
    assertTrue(iterator.next().holder().is("memberrebinding4.Memberrebinding$Inner"));
    assertTrue(iterator.next().holder().is("memberrebinding4.subpackage.PublicInterface"));
    assertFalse(iterator.hasNext());
  }

  private static void inspect4(DexInspector inspector) {
    MethodSubject main = inspector.clazz("memberrebinding4.Memberrebinding").method(TEST);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isInvoke);
    assertTrue(iterator.next().holder().is("memberrebinding4.Memberrebinding$Inner"));
    assertTrue(iterator.next().holder().is("memberrebinding4.subpackage.PublicInterface"));
    assertFalse(iterator.hasNext());
  }

  private static class TestConfiguration {

    private enum AndroidVersion {
      PRE_N,
      N
    }

    final String name;
    final Frontend kind;
    final AndroidVersion version;
    final Consumer<DexInspector> originalInspection;
    final Consumer<DexInspector> processedInspection;

    private TestConfiguration(String name,
        Frontend kind,
        AndroidVersion version,
        Consumer<DexInspector> originalInspection,
        Consumer<DexInspector> processedInspection) {
      this.name = name;
      this.kind = kind;
      this.version = version;
      this.originalInspection = originalInspection;
      this.processedInspection = processedInspection;
    }

    public static void add(ImmutableList.Builder<TestConfiguration> builder,
        String name,
        AndroidVersion version,
        Consumer<DexInspector> originalInspection,
        Consumer<DexInspector> processedInspection) {
      if (version == AndroidVersion.PRE_N) {
        builder.add(new TestConfiguration(name, Frontend.DEX, version, originalInspection,
            processedInspection));
      }
      builder.add(new TestConfiguration(name, Frontend.JAR, version, originalInspection,
          processedInspection));
    }

    public Path getDexPath() {
      return getBuildPath().resolve(name).resolve("classes.dex");
    }

    public Path getJarPath() {
      return getBuildPath().resolve(name + ".jar");
    }

    public Path getBuildPath() {
      switch (version) {
        case PRE_N:
          return Paths.get(ToolHelper.EXAMPLES_BUILD_DIR);
        case N:
          return Paths.get(ToolHelper.EXAMPLES_ANDROID_N_BUILD_DIR);
        default:
          Assert.fail();
          return null;
      }
    }

    public int getMinApiLevel() {
      switch (version) {
        case PRE_N:
          return AndroidApiLevel.getDefault().getLevel();
        case N:
          return AndroidApiLevel.N.getLevel();
        default:
          Assert.fail();
          return -1;
      }
    }

    public String toString() {
      return name + " " + kind;
    }
  }

  @Parameters(name = "{0}")
  public static Collection<TestConfiguration> data() {
    ImmutableList.Builder<TestConfiguration> builder = ImmutableList.builder();
    TestConfiguration.add(builder, "memberrebinding", TestConfiguration.AndroidVersion.PRE_N,
        MemberRebindingTest::inspectOriginalMain, MemberRebindingTest::inspectMain);
    TestConfiguration.add(builder, "memberrebinding2", TestConfiguration.AndroidVersion.PRE_N,
        MemberRebindingTest::inspectOriginalMain2, MemberRebindingTest::inspectMain2);
    TestConfiguration.add(builder, "memberrebinding3", TestConfiguration.AndroidVersion.PRE_N,
        MemberRebindingTest::inspectOriginal3, MemberRebindingTest::inspect3);
    TestConfiguration.add(builder, "memberrebinding4", TestConfiguration.AndroidVersion.N,
        MemberRebindingTest::inspectOriginal4, MemberRebindingTest::inspect4);
    return builder.build();
  }

  @Test
  public void memberRebindingTest() throws IOException, InterruptedException, ExecutionException {
    Assume.assumeTrue(ToolHelper.artSupported() || ToolHelper.compareAgaintsGoldenFiles());

    String out = temp.getRoot().getCanonicalPath();
    Path processed = Paths.get(out, "classes.dex");

    if (kind == Frontend.DEX) {
      DexInspector inspector = new DexInspector(originalDex);
      originalInspection.accept(inspector);
    }

    DexInspector inspector = new DexInspector(processed);
    inspection.accept(inspector);

    // We don't run Art, as the test R8RunExamplesTest already does that.
    // ToolHelper.checkArtOutputIdentical(originalDex, processed, mainClass, null);
  }
}
