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

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

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;

public class IncludeDescriptorClassesTest extends TestBase {
  private class Result {
    final CodeInspector inspector;
    final CodeInspector proguardedInspector;

    Result(CodeInspector inspector, CodeInspector proguardedInspector) {
      this.inspector = inspector;
      this.proguardedInspector = proguardedInspector;
    }

    void assertKept(Class clazz) {
      assertTrue(inspector.clazz(clazz.getCanonicalName()).isPresent());
      assertFalse(inspector.clazz(clazz.getCanonicalName()).isRenamed());
      if (proguardedInspector != null) {
        assertTrue(proguardedInspector.clazz(clazz).isPresent());
      }
    }

    // NOTE: 'synchronized' is supposed to disable inlining of this method.
    synchronized void assertRemoved(Class clazz) {
      assertFalse(inspector.clazz(clazz.getCanonicalName()).isPresent());
      if (proguardedInspector != null) {
        assertFalse(proguardedInspector.clazz(clazz).isPresent());
      }
    }

    void assertRenamed(Class clazz) {
      assertTrue(inspector.clazz(clazz.getCanonicalName()).isPresent());
      assertTrue(inspector.clazz(clazz.getCanonicalName()).isRenamed());
      if (proguardedInspector != null) {
        assertTrue(proguardedInspector.clazz(clazz).isPresent());
        assertTrue(proguardedInspector.clazz(clazz).isRenamed());
      }
    }
  }

  private List<Class<?>> applicationClasses =
      ImmutableList.of(
          ClassWithNativeMethods.class,
          NativeArgumentType.class,
          NativeReturnType.class,
          StaticFieldType.class,
          InstanceFieldType.class);
  private List<Class> mainClasses = ImmutableList.of(
      MainCallMethod1.class, MainCallMethod2.class, MainCallMethod3.class);

  Result runTest(Class mainClass, Path proguardConfig) throws Exception {
    List<Class<?>> classes = new ArrayList<>(applicationClasses);
    classes.add(mainClass);

    CodeInspector inspector = new CodeInspector(compileWithR8(classes, proguardConfig));

    CodeInspector proguardedInspector = null;
    // Actually running Proguard should only be during development.
    if (isRunProguard()) {
      Path proguardedJar = temp.newFolder().toPath().resolve("proguarded.jar");
      Path proguardedMap = temp.newFolder().toPath().resolve("proguarded.map");
      ToolHelper.runProguard(jarTestClasses(classes), proguardedJar, proguardConfig, proguardedMap);
      proguardedInspector = new CodeInspector(readJar(proguardedJar), proguardedMap);
    }

    return new Result(inspector, proguardedInspector);
  }

  @Test
  public void testNoIncludesDescriptorClasses() throws Exception {
    for (Class mainClass : mainClasses) {
      List<Class> allClasses = new ArrayList<>(applicationClasses);
      allClasses.add(mainClass);

      Path proguardConfig = writeTextToTempFile(
          keepMainProguardConfiguration(mainClass),
          "-keepclasseswithmembers class * {   ",
          "  <fields>;                         ",
          "  native <methods>;                 ",
          "}                                   ",
          "-allowaccessmodification            ",
          "-printmapping                       "
      );

      Result result = runTest(mainClass, proguardConfig);

      result.assertKept(ClassWithNativeMethods.class);
      // Return types are not removed as they can be needed for verification.
      // See b/112517039.
      result.assertRenamed(NativeReturnType.class);
      // Argument type is not removed due to the concern about the broken type hierarchy.
      result.assertRenamed(NativeArgumentType.class);
      // Field type is not removed due to the concern about the broken type hierarchy.
      result.assertRenamed(InstanceFieldType.class);
      result.assertRenamed(StaticFieldType.class);
    }
  }

  @Test
  public void testKeepClassesWithMembers() throws Exception {
    for (Class mainClass : mainClasses) {
      Path proguardConfig = writeTextToTempFile(
          keepMainProguardConfiguration(mainClass),
          "-keepclasseswithmembers,includedescriptorclasses class * {  ",
          "  <fields>;                                                 ",
          "  native <methods>;                                         ",
          "}                                                           ",
          "-allowaccessmodification                                    ",
          "-printmapping                                               "
      );

      Result result = runTest(mainClass, proguardConfig);

      // With includedescriptorclasses return type, argument type ad field type are not renamed.
      result.assertKept(ClassWithNativeMethods.class);
      result.assertKept(NativeArgumentType.class);
      result.assertKept(NativeReturnType.class);
      result.assertKept(InstanceFieldType.class);
      result.assertKept(StaticFieldType.class);
    }
  }

  @Test
  public void testKeepClassMembers() throws Exception {
    for (Class mainClass : mainClasses) {
      Path proguardConfig = writeTextToTempFile(
          keepMainProguardConfiguration(mainClass),
          "-keepclassmembers,includedescriptorclasses class * {  ",
          "  <fields>;                                           ",
          "  native <methods>;                                   ",
          "}                                                     ",
          "-allowaccessmodification                              ",
          "-printmapping                                         "
      );

      Result result = runTest(mainClass, proguardConfig);

      // With includedescriptorclasses return type and argument type are not renamed.
      result.assertRenamed(ClassWithNativeMethods.class);
      result.assertKept(NativeArgumentType.class);
      result.assertKept(NativeReturnType.class);
      result.assertKept(InstanceFieldType.class);
      result.assertKept(StaticFieldType.class);
    }
  }

    @Test
    public void testKeepClassMemberNames() throws Exception {
      for (Class mainClass : mainClasses) {
        Path proguardConfig = writeTextToTempFile(
            keepMainProguardConfiguration(mainClass),
            // same as -keepclassmembers,allowshrinking,includedescriptorclasses
            "-keepclassmembernames,includedescriptorclasses class * {  ",
            "  <fields>;                                               ",
            "  native <methods>;                                       ",
            "}                                                         ",
            "-allowaccessmodification                                  ",
            "-printmapping                                             "
        );

        Result result = runTest(mainClass, proguardConfig);

        boolean useNativeArgumentType =
            mainClass == MainCallMethod1.class || mainClass == MainCallMethod3.class;
        boolean useNativeReturnType =
            mainClass == MainCallMethod2.class || mainClass == MainCallMethod3.class;

        result.assertRenamed(ClassWithNativeMethods.class);
        if (useNativeArgumentType) {
          result.assertKept(NativeArgumentType.class);
        } else {
          result.assertRemoved(NativeArgumentType.class);
        }

        if (useNativeReturnType) {
          result.assertKept(NativeReturnType.class);
        } else {
          result.assertRemoved(NativeReturnType.class);
        }

        result.assertRemoved(InstanceFieldType.class);
        result.assertRemoved(StaticFieldType.class);
      }
    }
}
