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

import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.DebuggeeState;
import java.nio.file.Path;
import java.util.stream.Stream;
import org.junit.Assume;
import org.junit.Test;

public class IincDebugTestRunner extends DebugTestBase {
  @Test
  public void compareDifferentRegister() throws Exception {
    compareOutput(IincDebugTestDump.dump(1, 2, false));
  }

  @Test
  public void compareLoadStoreSameRegister() throws Exception {
    compareOutput(IincDebugTestDump.dump(1, 1, false));
  }

  @Test
  public void compareIinc() throws Exception {
    compareOutput(IincDebugTestDump.dump(1, 1, true));
  }

  @Test
  public void stepDifferentRegister() throws Exception {
    stepOutput(IincDebugTestDump.dump(1, 2, false));
  }

  @Test
  public void stepLoadStoreSameRegister() throws Exception {
    stepOutput(IincDebugTestDump.dump(1, 1, false));
  }

  @Test
  public void stepIinc() throws Exception {
    stepOutput(IincDebugTestDump.dump(1, 1, true));
  }

  private void compareOutput(byte[] clazz) throws Exception {
    Path inputJar = buildInput(clazz);
    ProcessResult runInput = ToolHelper.runJava(inputJar, IincDebugTestDump.CLASS_NAME);
    assertEquals(0, runInput.exitCode);
    ProcessResult runCf = ToolHelper.runJava(buildCf(inputJar), IincDebugTestDump.CLASS_NAME);
    assertEquals(0, runCf.exitCode);
    assertEquals(runInput.toString(), runCf.toString());
    String runDex =
        ToolHelper.runArtNoVerificationErrors(
            buildDex(inputJar).toString(), IincDebugTestDump.CLASS_NAME);
    assertEquals(runInput.stdout, runDex);
  }

  private void stepOutput(byte[] clazz) throws Exception {
    // See verifyStateLocation in DebugTestBase.
    Assume.assumeTrue(
        "Streaming on Dalvik DEX runtimes has some unknown interference issue",
        ToolHelper.getDexVm().getVersion().isAtLeast(Version.V6_0_1));
    Assume.assumeTrue(
        "Skipping test "
            + testName.getMethodName()
            + " because debug tests are not yet supported on Windows",
        !ToolHelper.isWindows());
    Path inputJar = buildInput(clazz);
    new DebugStreamComparator()
        .add("Input", streamDebugTest(new CfDebugTestConfig(inputJar)))
        .add("R8/DEX", streamDebugTest(new DexDebugTestConfig(buildDex(inputJar))))
        .add("R8/CF", streamDebugTest(new CfDebugTestConfig(buildCf(inputJar))))
        .compare();
  }

  private Stream<DebuggeeState> streamDebugTest(DebugTestConfig config) throws Exception {
    return streamDebugTest(config, IincDebugTestDump.CLASS_NAME, ANDROID_FILTER);
  }

  private Path buildInput(byte[] clazz) {
    Path inputJar = temp.getRoot().toPath().resolve("input.jar");
    ArchiveConsumer inputJarConsumer = new ArchiveConsumer(inputJar);
    inputJarConsumer.accept(ByteDataView.of(clazz), IincDebugTestDump.DESCRIPTOR, null);
    inputJarConsumer.finished(null);
    return inputJar;
  }

  private Path buildDex(Path inputJar) throws Exception {
    Path dexJar = temp.getRoot().toPath().resolve("r8dex.jar");
    build(inputJar, new DexIndexedConsumer.ArchiveConsumer(dexJar));
    return dexJar;
  }

  private Path buildCf(Path inputJar) throws Exception {
    Path cfJar = temp.getRoot().toPath().resolve("r8cf.jar");
    build(inputJar, new ArchiveConsumer(cfJar));
    return cfJar;
  }

  private void build(Path inputJar, ProgramConsumer consumer) throws Exception {
    Builder builder =
        R8Command.builder()
            .setMode(CompilationMode.DEBUG)
            .setProgramConsumer(consumer)
            .addProgramFiles(inputJar);
    if ((consumer instanceof ClassFileConsumer)) {
      builder.addLibraryFiles(ToolHelper.getJava8RuntimeJar());
    } else {
      builder.addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()));
    }
    ToolHelper.runR8(builder.build(), options -> options.invalidDebugInfoFatal = true);
  }
}
