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

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

import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.utils.BooleanUtils;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Set;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ExtractMarkerTest extends TestBase {
  private static final String CLASS_FILE =
      ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class";

  private final TestParameters parameters;
  private boolean includeClassesChecksum;

  @Parameterized.Parameters(name = "{0}, includeClassesChecksum: {1}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimes().withAllApiLevels().build(), BooleanUtils.values());
  }

  public ExtractMarkerTest(TestParameters parameters, boolean includeClassesChecksum) {
    this.parameters = parameters;
    this.includeClassesChecksum = includeClassesChecksum;
  }

  private void verifyMarkerDex(Marker marker, Tool tool) {
    assertEquals(tool, marker.getTool());
    assertEquals(Version.LABEL, marker.getVersion());
    assertEquals(CompilationMode.DEBUG.toString().toLowerCase(), marker.getCompilationMode());
    assertEquals(parameters.getApiLevel().getLevel(), marker.getMinApi().intValue());
    assertEquals(includeClassesChecksum, marker.getHasChecksums());
  }

  @Test
  public void extractMarkerTestDex() throws CompilationFailedException {
    Assume.assumeTrue(parameters.getRuntime().isDex());

    boolean[] testExecuted = {false};
    D8.run(
        D8Command.builder()
            .addProgramFiles(Paths.get(CLASS_FILE))
            .setMinApiLevel(parameters.getApiLevel().getLevel())
            .setIncludeClassesChecksum(includeClassesChecksum)
            .setProgramConsumer(
                new DexIndexedConsumer.ForwardingConsumer(null) {
                  @Override
                  public void accept(
                      int fileIndex,
                      ByteDataView data,
                      Set<String> descriptors,
                      DiagnosticsHandler handler) {
                    Marker marker;
                    try {
                      Collection<Marker> markers =
                          ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData());
                      assertEquals(1, markers.size());
                      marker = markers.iterator().next();
                    } catch (Exception e) {
                      throw new RuntimeException(e);
                    }
                    verifyMarkerDex(marker, Tool.D8);
                    testExecuted[0] = true;
                  }
                })
            .build());
    assertTrue(testExecuted[0]);
  }

  private static void verifyMarkerCf(Marker marker, Tool tool) {
    assertEquals(tool, marker.getTool());
    assertEquals(Version.LABEL, marker.getVersion());
    assertEquals(CompilationMode.DEBUG.toString().toLowerCase(), marker.getCompilationMode());
    assertFalse(marker.getHasChecksums());
  }

  @Test
  public void extractMarkerTestCf() throws CompilationFailedException {
    Assume.assumeTrue(parameters.getRuntime().isCf());
    Assume.assumeFalse(includeClassesChecksum);

    boolean[] testExecuted = {false};
    R8.run(
        R8Command.builder()
            .addProgramFiles(Paths.get(CLASS_FILE))
            .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
            .setMode(CompilationMode.DEBUG)
            .setDisableTreeShaking(true)
            .setProgramConsumer(
                new ClassFileConsumer.ForwardingConsumer(null) {
                  @Override
                  public void accept(
                      ByteDataView data, String descriptor, DiagnosticsHandler handler) {
                    Marker marker;
                    try {
                      Collection<Marker> markers =
                          ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData());
                      assertEquals(1, markers.size());
                      marker = markers.iterator().next();
                    } catch (Exception e) {
                      throw new RuntimeException(e);
                    }
                    verifyMarkerCf(marker, Tool.R8);
                    testExecuted[0] = true;
                  }
                })
            .build());
    assertTrue(testExecuted[0]);
  }

  @Test
  public void backendValueCompatibilityTestForMinApi() {
    DexItemFactory factory = new DexItemFactory();
    DexString markerString =
        factory.createString(
            "~~D8{\"compilation-mode\":\"debug\",\"has-checksums\":false,"
                + "\"min-api\":21,\"sha-1\":\"engineering\",\"version\":\"main\" }");
    assertEquals("dex", Marker.parse(markerString).getBackend());
  }

  @Test
  public void backendValueCompatibilityTestForR8Cf() {
    DexItemFactory factory = new DexItemFactory();
    DexString markerString =
        factory.createString(
            "~~R8{\"compilation-mode\":\"release\",\"has-checksums\":true,"
                + "\"sha-1\":\"engineering\",\"version\":\"main\" }");
    assertEquals("cf", Marker.parse(markerString).getBackend());
  }
}
