// 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(SOURCE_FILE, 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(SOURCE_FILE, 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);
  }
}
