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

import static org.junit.Assert.assertTrue;

import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.debug.DebugTestConfig.RuntimeKind;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/** Tests renaming of class and method names and corresponding proguard map output. */
@RunWith(Parameterized.class)
public class MinificationTest extends DebugTestBase {

  private static final String SOURCE_FILE = "Minified.java";

  @Parameterized.Parameters(name = "backend:{0} minification:{1} proguardMap:{2}")
  public static Collection minificationControl() {
    ImmutableList.Builder<Object> builder = ImmutableList.builder();
    for (RuntimeKind kind : RuntimeKind.values()) {
      for (MinifyMode mode : MinifyMode.values()) {
        builder.add((Object) new Object[] {kind, mode, false});
        if (mode.isMinify()) {
          builder.add((Object) new Object[] {kind, mode, true});
        }
      }
    }
    return builder.build();
  }

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

  private final RuntimeKind runtimeKind;
  private final MinifyMode minificationMode;
  private final boolean writeProguardMap;

  public MinificationTest(
      RuntimeKind runtimeKind, MinifyMode minificationMode, boolean writeProguardMap) {
    this.runtimeKind = runtimeKind;
    this.minificationMode = minificationMode;
    this.writeProguardMap = writeProguardMap;
  }

  private boolean minifiedNames() {
    return minificationMode.isMinify() && !writeProguardMap;
  }

  private DebugTestConfig getTestConfig() throws Throwable {
    List<String> proguardConfigurations = Collections.emptyList();
    ImmutableList.Builder<String> proguardConfigurationBuilder = ImmutableList.builder();
    if (!minificationMode.isMinify()) {
      proguardConfigurationBuilder.add("-dontobfuscate");
    } else if (minificationMode.isAggressive()) {
      proguardConfigurationBuilder.add("-overloadaggressively");
    }
    proguardConfigurationBuilder.add(
        "-keep public class Minified { public static void main(java.lang.String[]); }");
    proguardConfigurationBuilder.add("-keepattributes SourceFile");
    proguardConfigurationBuilder.add("-keepattributes LineNumberTable");
    proguardConfigurations = proguardConfigurationBuilder.build();

    Path outputPath = temp.getRoot().toPath().resolve("classes.zip");
    Path proguardMap = writeProguardMap ? temp.getRoot().toPath().resolve("proguard.map") : null;
    OutputMode outputMode =
        runtimeKind == RuntimeKind.CF ? OutputMode.ClassFile : OutputMode.DexIndexed;
    R8Command.Builder builder =
        R8Command.builder()
            .addProgramFiles(DEBUGGEE_JAR)
            .setOutput(outputPath, outputMode)
            .setMode(CompilationMode.DEBUG);
    if (runtimeKind == RuntimeKind.DEX) {
      AndroidApiLevel minSdk = ToolHelper.getMinApiLevelForDexVm();
      builder.setMinApiLevel(minSdk.getLevel()).addLibraryFiles(ToolHelper.getAndroidJar(minSdk));
    } else if (runtimeKind == RuntimeKind.CF) {
      builder.addLibraryFiles(ToolHelper.getJava8RuntimeJar());
    }
    if (proguardMap != null) {
      builder.setProguardMapOutputPath(proguardMap);
    }
    if (!proguardConfigurations.isEmpty()) {
      builder.addProguardConfiguration(proguardConfigurations, Origin.unknown());
    }
    // Disable line number optimization if we're not using a Proguard map.
    ToolHelper.runR8(
        builder.build(),
        proguardMap == null
            ? (oc -> oc.lineNumberOptimization = LineNumberOptimization.OFF)
            : null);

    switch (runtimeKind) {
      case CF:
        {
          CfDebugTestConfig config = new CfDebugTestConfig(outputPath);
          config.setProguardMap(proguardMap);
          return config;
        }
      case DEX:
        {
          DexDebugTestConfig config = new DexDebugTestConfig(outputPath);
          config.setProguardMap(proguardMap);
          return config;
        }
      default:
        throw new Unreachable();
    }
  }

  @Test
  public void testBreakInMainClass() throws Throwable {
    final String className = "Minified";
    final String methodName = minifiedNames() ? "a" : "test";
    final String signature = "()V";
    final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
    final String innerMethodName = minifiedNames() ? "a" : "innerTest";
    final String innerSignature = "()I";
    DebugTestConfig config = getTestConfig();
    checkStructure(
        config,
        className,
        MethodSignature.fromSignature(methodName, signature),
        innerClassName,
        MethodSignature.fromSignature(innerMethodName, innerSignature));
    runDebugTest(
        config,
        className,
        breakpoint(className, methodName, signature),
        run(),
        checkMethod(className, methodName, signature),
        checkLine(SOURCE_FILE, 14),
        stepOver(INTELLIJ_FILTER),
        checkMethod(className, methodName, signature),
        checkLine(SOURCE_FILE, 15),
        stepInto(INTELLIJ_FILTER),
        checkMethod(innerClassName, innerMethodName, innerSignature),
        checkLine(8),
        run());
  }

  @Test
  public void testBreakInPossiblyRenamedClass() throws Throwable {
    final String className = "Minified";
    final String innerClassName = minifiedNames() ? "a" : "Minified$Inner";
    final String innerMethodName = minifiedNames() ? "a" : "innerTest";
    final String innerSignature = "()I";
    DebugTestConfig config = getTestConfig();
    checkStructure(
        config,
        className,
        innerClassName,
        MethodSignature.fromSignature(innerMethodName, innerSignature));
    runDebugTest(
        config,
        className,
        breakpoint(innerClassName, innerMethodName, innerSignature),
        run(),
        checkMethod(innerClassName, innerMethodName, innerSignature),
        checkLine(8),
        run());
  }

  private void checkStructure(
      DebugTestConfig config,
      String className,
      MethodSignature method,
      String innerClassName,
      MethodSignature innerMethod)
      throws Throwable {
    Path proguardMap = config.getProguardMap();
    String mappingFile = proguardMap == null ? null : proguardMap.toString();
    CodeInspector inspector = new CodeInspector(config.getPaths(), mappingFile, null);
    ClassSubject clazz = inspector.clazz(className);
    assertTrue(clazz.isPresent());
    if (method != null) {
      assertTrue(clazz.method(method).isPresent());
    }
    ClassSubject innerClass = inspector.clazz(innerClassName);
    assertTrue(innerClass.isPresent());
    assertTrue(innerClass.method(innerMethod).isPresent());
  }

  private void checkStructure(
      DebugTestConfig config, String className, String innerClassName, MethodSignature innerMethod)
      throws Throwable {
    checkStructure(config, className, null, innerClassName, innerMethod);
  }
}
