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

import static org.junit.Assert.assertTrue;

import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.FrameInspector;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import org.apache.harmony.jpda.tests.framework.jdwp.Value;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/** Tests local variable information. */
@RunWith(Parameterized.class)
public class BreakPointEventsTestRunner extends DebugTestBase {

  public static final Class<BreakPointEventsTest> CLASS = BreakPointEventsTest.class;
  public static final String FILE = CLASS.getSimpleName() + ".java";

  private static Path getClassFilePath() {
    return ToolHelper.getClassFileForTestClass(CLASS);
  }

  public static DebugTestConfig cfConfig() {
    return new CfDebugTestConfig(ToolHelper.getClassPathForTests());
  }

  public static DebugTestConfig d8Config() {
    return new D8DebugTestConfig().compileAndAdd(getStaticTemp(), getClassFilePath());
  }

  public static DebugTestConfig r8CfConfig() throws Exception {
    Path outCf = getStaticTemp().getRoot().toPath().resolve("cf.jar");
    R8.run(
        R8Command.builder()
            .setMode(CompilationMode.DEBUG)
            .addProgramFiles(getClassFilePath())
            .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
            .setProgramConsumer(new ClassFileConsumer.ArchiveConsumer(outCf))
            .build());
    return new CfDebugTestConfig(ToolHelper.getClassPathForTests()).addPaths(outCf);
  }

  public static DebugTestConfig dxConfig() throws Exception {
    Path cwd = ToolHelper.getClassPathForTests().toAbsolutePath();
    Path test = cwd.relativize(getClassFilePath().toAbsolutePath());
    Path out = getStaticTemp().newFolder().toPath().resolve("classes.dex").toAbsolutePath();
    ProcessResult result = ToolHelper.runDX(cwd, "--output=" + out, test.toString());
    assertTrue(result.stderr, 0 == result.exitCode);
    DebugTestConfig config = new DexDebugTestConfig();
    config.addPaths(out);
    return config;
  }

  public void printConfig(String name, DebugTestConfig config) throws Exception {
    new DebugStreamComparator()
        .add(name, streamDebugTest(config, CLASS.getCanonicalName(), NO_FILTER))
        .setPrintStates(true)
        .setPrintMethod(true)
        .setPrintVariables(true)
        .setFilter(s -> s.getSourceFile().equals(FILE))
        .run();
  }

  // The main method will single-step each configuration of the test. It cannot be made a test as
  // the event streams are unequal due to ART vs JVM line change on return and DX incorrect locals.
  public static void main(String[] args) throws Exception {
    getStaticTemp().create();
    try {
      BreakPointEventsTestRunner runner = new BreakPointEventsTestRunner("unused name");
      System.out.println("\n============== CF single stepping: ");
      runner.printConfig("CF", cfConfig());
      System.out.println("\n============== D8 single stepping: ");
      runner.printConfig("D8", d8Config());
      System.out.println("\n============== DX single stepping: ");
      runner.printConfig("DX", dxConfig());
    } finally {
      getStaticTemp().delete();
    }
  }

  @Parameters(name = "{0}")
  public static Collection<String> configs() {
    return Arrays.asList("CF", "D8", "R8/CF");
  }

  private final DebugTestConfig config;

  public BreakPointEventsTestRunner(String name) throws Exception {
    if (name.equals("CF")) {
      config = cfConfig();
    } else if (name.equals("D8")) {
      config = d8Config();
    } else {
      assert name.equals("R8/CF");
      config = r8CfConfig();
    }
  }

  @Test
  public void testSingleLineDeclarations() throws Throwable {
    int bLine = 11;
    Value bValueOne = Value.createInt(1);
    Value bValueTwo = Value.createInt(2);
    runDebugTest(
        config,
        CLASS.getCanonicalName(),
        // Install breakpoint on b which is hit 6 times during execution.
        breakpoint(CLASS.getCanonicalName(), "b"),
        // First set of declarations will have respectively {}, {x}, and {x,y} visible in the frame.
        run(),
        checkLine(FILE, bLine),
        inspect(
            i -> {
              FrameInspector frame = i.getFrame(1);
              frame.checkNoLocal("x");
              frame.checkNoLocal("y");
              frame.checkNoLocal("z");
            }),
        run(),
        checkLine(FILE, bLine),
        inspect(
            i -> {
              FrameInspector frame = i.getFrame(1);
              frame.checkLocal("x", bValueOne);
              frame.checkNoLocal("y");
              frame.checkNoLocal("z");
            }),
        run(),
        checkLine(FILE, bLine),
        inspect(
            i -> {
              FrameInspector frame = i.getFrame(1);
              frame.checkLocal("x", bValueOne);
              frame.checkLocal("y", bValueOne);
              frame.checkNoLocal("z");
            }),
        // Second set of declarations should appear the same, only with another value.
        run(),
        checkLine(FILE, bLine),
        inspect(
            i -> {
              FrameInspector frame = i.getFrame(1);
              // This fails on DX compiled output since x will appear visible here.
              frame.checkNoLocal("x");
              frame.checkNoLocal("y");
              frame.checkNoLocal("z");
            }),
        run(),
        checkLine(FILE, bLine),
        inspect(
            i -> {
              FrameInspector frame = i.getFrame(1);
              frame.checkLocal("x", bValueTwo);
              frame.checkNoLocal("y");
              frame.checkNoLocal("z");
            }),
        run(),
        checkLine(FILE, bLine),
        inspect(
            i -> {
              FrameInspector frame = i.getFrame(1);
              frame.checkLocal("x", bValueTwo);
              frame.checkLocal("y", bValueTwo);
              frame.checkNoLocal("z");
            }),
        // Install additonal breakpoint on return to main so we identify program execution ended.
        breakpoint(CLASS.getCanonicalName(), "main", 22),
        run(),
        checkLine(FILE, 22),
        run());
  }
}
