// Copyright (c) 2018, 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.shaking.examples;

import com.android.tools.r8.shaking.TreeShakingTest;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
import org.junit.Assume;
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 TreeShaking1Test extends TreeShakingTest {

  @Parameters(name = "mode:{0}-{1} minify:{2}")
  public static Collection<Object[]> data() {
    List<Object[]> parameters = new ArrayList<>();
    for (MinifyMode minify : MinifyMode.values()) {
      parameters.add(new Object[] {Frontend.JAR, Backend.CF, minify});
      parameters.add(new Object[] {Frontend.JAR, Backend.DEX, minify});
      parameters.add(new Object[] {Frontend.DEX, Backend.DEX, minify});
    }
    return parameters;
  }

  public TreeShaking1Test(Frontend frontend, Backend backend, MinifyMode minify) {
    super("examples/shaking1", "shaking1.Shaking", frontend, backend, minify);
  }

  @Test
  public void testKeeprules() throws Exception {
    runTest(
        TreeShaking1Test::shaking1HasNoClassUnused,
        null,
        null,
        ImmutableList.of("src/test/examples/shaking1/keep-rules.txt"));
  }

  @Test
  public void testKeeprulesEmpty() throws Exception {
    runTest(
        TreeShaking1Test::shaking1HasNoClassUnused,
        null,
        null,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules.txt", "src/test/proguard/valid/empty.flags"));
  }

  @Test
  public void testKeeprulesEmptyEmpty() throws Exception {
    runTest(
        TreeShaking1Test::shaking1HasNoClassUnused,
        null,
        null,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules.txt",
            "src/test/proguard/valid/empty.flags",
            "src/test/proguard/valid/empty.flags"));
  }

  @Test
  public void testKeeprulesdontshrink() throws Exception {
    runTest(
        null,
        null,
        TreeShakingTest::checkSameStructure,
        ImmutableList.of("src/test/examples/shaking1/keep-rules-dont-shrink.txt"));
  }

  @Test
  public void testKeeprulesdontshrinkEmpty() throws Exception {
    runTest(
        null,
        null,
        TreeShakingTest::checkSameStructure,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules-dont-shrink.txt",
            "src/test/proguard/valid/empty.flags"));
  }

  @Test
  public void testKeeprulesdontshrinkEmptyEmpty() throws Exception {
    runTest(
        null,
        null,
        TreeShakingTest::checkSameStructure,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules-dont-shrink.txt",
            "src/test/proguard/valid/empty.flags",
            "src/test/proguard/valid/empty.flags"));
  }

  @Test
  public void testKeeprulesprintusage() throws Exception {
    runTest(
        null, null, null, ImmutableList.of("src/test/examples/shaking1/keep-rules-printusage.txt"));
  }

  @Test
  public void testKeeprulesprintusageEmpty() throws Exception {
    runTest(
        null,
        null,
        null,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules-printusage.txt",
            "src/test/proguard/valid/empty.flags"));
  }

  @Test
  public void testKeeprulesprintusageEmptyEmpty() throws Exception {
    runTest(
        null,
        null,
        null,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules-printusage.txt",
            "src/test/proguard/valid/empty.flags",
            "src/test/proguard/valid/empty.flags"));
  }

  @Test
  public void testKeeprulesrepackaging() throws Exception {
    Assume.assumeFalse(getMinify() == MinifyMode.NONE);
    runTest(
        TreeShaking1Test::shaking1IsCorrectlyRepackaged,
        null,
        null,
        ImmutableList.of("src/test/examples/shaking1/keep-rules-repackaging.txt"));
  }

  @Test
  public void testKeeprulesrepackagingEmpty() throws Exception {
    Assume.assumeFalse(getMinify() == MinifyMode.NONE);
    runTest(
        TreeShaking1Test::shaking1IsCorrectlyRepackaged,
        null,
        null,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules-repackaging.txt",
            "src/test/proguard/valid/empty.flags"));
  }

  @Test
  public void testKeeprulesrepackagingEmptyEmpty() throws Exception {
    Assume.assumeFalse(getMinify() == MinifyMode.NONE);
    runTest(
        TreeShaking1Test::shaking1IsCorrectlyRepackaged,
        null,
        null,
        ImmutableList.of(
            "src/test/examples/shaking1/keep-rules-repackaging.txt",
            "src/test/proguard/valid/empty.flags",
            "src/test/proguard/valid/empty.flags"));
  }

  private static void shaking1IsCorrectlyRepackaged(CodeInspector inspector) {
    inspector.forAllClasses(
        clazz -> {
          String descriptor = clazz.getFinalDescriptor();
          Assert.assertTrue(
              descriptor,
              DescriptorUtils.getSimpleClassNameFromDescriptor(descriptor).equals("Shaking")
                  || DescriptorUtils.getPackageNameFromDescriptor(descriptor).equals("repackaged"));
        });
  }

  private static void shaking1HasNoClassUnused(CodeInspector inspector) {
    Assert.assertFalse(inspector.clazz("shaking1.Unused").isPresent());
    ClassSubject used = inspector.clazz("shaking1.Used");
    Assert.assertTrue(used.isPresent());
    Assert.assertTrue(
        used.method("java.lang.String", "aMethodThatIsNotUsedButKept", Collections.emptyList())
            .isPresent());
    Assert.assertTrue(used.field("int", "aStaticFieldThatIsNotUsedButKept").isPresent());
    // Rewriting of <clinit> moves the initialization of aStaticFieldThatIsNotUsedButKept
    // from <clinit> code into statics value section of the dex file.
    Assert.assertFalse(used.clinit().isPresent());
  }
}
