// Copyright (c) 2020, 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.tracereferences;

import static com.android.tools.r8.utils.MissingDefinitionsDiagnosticTestUtils.getMissingClassMessage;
import static com.android.tools.r8.utils.MissingDefinitionsDiagnosticTestUtils.getMissingFieldMessage;
import static com.android.tools.r8.utils.MissingDefinitionsDiagnosticTestUtils.getMissingMethodMessage;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DiagnosticsChecker;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.diagnostic.DefinitionContext;
import com.android.tools.r8.diagnostic.internal.DefinitionMethodContextImpl;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FieldReferenceUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.MethodReferenceUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.google.common.collect.ImmutableList;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import kotlin.text.Charsets;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class TraceReferencesCommandTest extends TestBase {
  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  public TraceReferencesCommandTest(TestParameters parameters) {
    parameters.assertNoneRuntime();
  }

  @Test(expected = CompilationFailedException.class)
  public void emptyBuilder() throws Throwable {
    TraceReferencesCommand.builder().build();
  }

  @Test(expected = CompilationFailedException.class)
  public void emptyRun() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No library specified",
        handler -> {
          TraceReferences.run(TraceReferencesCommand.builder(handler).build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void emptyRunCommandLine() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "Missing command",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(new String[] {}, Origin.unknown(), handler).build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void unsupportedCommandCommandLine() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "Missing command, specify one of 'check' or '--keep-rules'",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(new String[] {"--xxx"}, Origin.unknown(), handler)
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void onlyLibrarySpecified() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No source specified",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.builder(handler)
                  .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void onlyLibrarySpecifiedCommandLine() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No source specified",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(
                      new String[] {
                        "--check", "--lib", ToolHelper.getAndroidJar(AndroidApiLevel.P).toString()
                      },
                      Origin.unknown(),
                      handler)
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void multipleCommandsSpecified() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "Multiple commands specified",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(
                      new String[] {"--check", "--keep-rules"}, Origin.unknown(), handler)
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void allowobfuscationWithoutKeepRule() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "Using '--allowobfuscation' requires command '--keep-rules'",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(
                      new String[] {"--check", "--allowobfuscation"}, Origin.unknown(), handler)
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void allowobfuscationMultiple() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No library specified",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(
                      new String[] {"--keep-rules", "--allowobfuscation", "--allowobfuscation"},
                      Origin.unknown(),
                      handler)
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void multipleFormatsCommandLine() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "Using '--output' requires command '--keep-rules'",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(
                      new String[] {"--check", "--output", "xxx"}, Origin.unknown(), handler)
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void outputMultiple() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "Option '--output' passed multiple times",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(
                      new String[] {"--keep-rules", "--output", "xxx", "--output", "xxx"},
                      Origin.unknown(),
                      handler)
                  .build());
        });
  }

  private String formatName(OutputFormat format) {
    if (format == OutputFormat.KEEP_RULES) {
      return "--keep-rules";
    }
    assertSame(format, OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION);
    return "--keep-rules";
  }

  enum OutputFormat {
    KEEP_RULES,
    KEEP_RULES_WITH_ALLOWOBFUSCATION
  }

  private static class StringValueStringConsumer implements StringConsumer {
    private StringBuilder builder = new StringBuilder();
    private boolean finished = false;

    @Override
    public void accept(String string, DiagnosticsHandler handler) {
      builder.append(string);
    }

    @Override
    public void finished(DiagnosticsHandler handler) {
      finished = true;
    }

    String get() {
      assert finished;
      return builder.toString();
    }
  }

  public void runAndCheckOutput(
      Path targetJar,
      Path sourceJar,
      OutputFormat format,
      String expected,
      Consumer<DiagnosticsChecker> diagnosticsCheckerConsumer)
      throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path output = dir.resolve("output.txt");
    DiagnosticsChecker diagnosticsChecker = new DiagnosticsChecker();
    StringValueStringConsumer stringConsumer = new StringValueStringConsumer();
    TraceReferencesConsumer consumer =
        TraceReferencesKeepRules.builder()
            .setAllowObfuscation(format == OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION)
            .setOutputConsumer(stringConsumer)
            .build();
    try {
      TraceReferences.run(
          TraceReferencesCommand.builder(diagnosticsChecker)
              .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
              .addTargetFiles(targetJar)
              .addSourceFiles(sourceJar)
              .setConsumer(new TraceReferencesCheckConsumer(consumer))
              .build());
      assertEquals(expected, stringConsumer.get());
      if (diagnosticsCheckerConsumer != null) {
        diagnosticsCheckerConsumer.accept(diagnosticsChecker);
      } else {
        assertEquals(0, diagnosticsChecker.errors.size());
        assertEquals(0, diagnosticsChecker.warnings.size());
        assertEquals(0, diagnosticsChecker.infos.size());
      }
    } catch (CompilationFailedException e) {
      if (diagnosticsCheckerConsumer != null) {
        diagnosticsCheckerConsumer.accept(diagnosticsChecker);
      }
      throw e;
    }

    List<String> args = new ArrayList<>();
    args.add(formatName(format));
    if (format == OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION) {
      args.add("--allowobfuscation");
    }
    args.addAll(
        ImmutableList.of(
            "--lib",
            ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
            "--target",
            targetJar.toString(),
            "--source",
            sourceJar.toString(),
            "--output",
            output.toString()));

    TraceReferences.run(TraceReferencesCommand.parse(args, Origin.unknown()).build());
    assertEquals(expected, FileUtils.readTextFile(output, Charsets.UTF_8));
  }

  public void runAndCheckOutput(
      List<Class<?>> targetClasses,
      List<Class<?>> sourceClasses,
      OutputFormat format,
      String expected)
      throws Throwable {
    runAndCheckOutput(targetClasses, sourceClasses, format, expected, null);
  }

  private Path zipWithTestClasses(Path zipFile, List<Class<?>> targetClasses) throws IOException {
    return ZipBuilder.builder(zipFile)
        .addFilesRelative(
            ToolHelper.getClassPathForTests(),
            targetClasses.stream()
                .map(ToolHelper::getClassFileForTestClass)
                .collect(Collectors.toList()))
        .build();
  }

  public void runAndCheckOutput(
      List<Class<?>> targetClasses,
      List<Class<?>> sourceClasses,
      OutputFormat format,
      String expected,
      Consumer<DiagnosticsChecker> diagnosticsCheckerConsumer)
      throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar = zipWithTestClasses(dir.resolve("target.jar"), targetClasses);
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), sourceClasses);
    runAndCheckOutput(targetJar, sourceJar, format, expected, diagnosticsCheckerConsumer);
  }

  @Test
  public void test_keepRules() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(Target.class),
        ImmutableList.of(Source.class),
        OutputFormat.KEEP_RULES,
        StringUtils.lines(
            ImmutableList.of(
                "-keep class com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                    + " {",
                "  public static void method(int);",
                "  int field;",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences")));
  }

  @Test
  public void test_keepRulesAllowObfuscation() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(Target.class),
        ImmutableList.of(Source.class),
        OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION,
        StringUtils.lines(
            ImmutableList.of(
                "-keep,allowobfuscation class"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target {",
                "  public static void method(int);",
                "  int field;",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences")));
  }

  @Test
  public void test_noOutput() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar = zipWithTestClasses(dir.resolve("target.jar"), ImmutableList.of(Target.class));
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), ImmutableList.of(Source.class));
    PrintStream originalOut = System.out;
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      System.setOut(new PrintStream(baos));
      TraceReferences.run(
          TraceReferencesCommand.builder()
              .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
              .addTargetFiles(targetJar)
              .addSourceFiles(sourceJar)
              .setConsumer(TraceReferencesConsumer.emptyConsumer())
              .build());
      assertEquals(0, baos.size());
    } finally {
      System.setOut(originalOut);
    }

    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      System.setOut(new PrintStream(baos));
      TraceReferences.run(
          TraceReferencesCommand.parse(
                  new String[] {
                    "--lib",
                    ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
                    "--check",
                    "--target",
                    targetJar.toString(),
                    "--source",
                    sourceJar.toString(),
                  },
                  Origin.unknown())
              .build());
      assertEquals(0, baos.size());
    } finally {
      System.setOut(originalOut);
    }
  }

  @Test
  public void test_stdoutOutput() throws Throwable {
    String expected =
        StringUtils.lines(
            ImmutableList.of(
                "-keep class"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target {",
                "  public static void method(int);",
                "  int field;",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences"));
    Path dir = temp.newFolder().toPath();
    Path targetJar = zipWithTestClasses(dir.resolve("target.jar"), ImmutableList.of(Target.class));
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), ImmutableList.of(Source.class));
    PrintStream originalOut = System.out;
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      System.setOut(new PrintStream(baos));
      TraceReferences.run(
          TraceReferencesCommand.parse(
                  new String[] {
                    "--lib",
                    ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
                    "--target",
                    targetJar.toString(),
                    "--source",
                    sourceJar.toString(),
                    "--keep-rules",
                  },
                  Origin.unknown())
              .build());
      assertEquals(expected, baos.toString(Charsets.UTF_8.name()));
    } finally {
      System.setOut(originalOut);
    }
  }

  @Test
  public void classFileInput() throws Throwable {
    String expected =
        StringUtils.lines(
            ImmutableList.of(
                "-keep class"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target {",
                "  public static void method(int);",
                "  int field;",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences"));
    Path output = temp.newFile().toPath();
    TraceReferencesKeepRules consumer =
        TraceReferencesKeepRules.builder().setOutputPath(output).build();
    TraceReferences.run(
        TraceReferencesCommand.builder()
            .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
            .addTargetFiles(ToolHelper.getClassFileForTestClass(Target.class))
            .addSourceFiles(ToolHelper.getClassFileForTestClass(Source.class))
            .setConsumer(consumer)
            .build());
    assertEquals(expected, FileUtils.readTextFile(output, Charsets.UTF_8));

    output = temp.newFile().toPath();
    TraceReferences.run(
        TraceReferencesCommand.parse(
                new String[] {
                  "--lib",
                  ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
                  "--target",
                  ToolHelper.getClassFileForTestClass(Target.class).toString(),
                  "--source",
                  ToolHelper.getClassFileForTestClass(Source.class).toString(),
                  "--output",
                  output.toString(),
                  "--keep-rules"
                },
                Origin.unknown())
            .build());
    assertEquals(expected, FileUtils.readTextFile(output, Charsets.UTF_8));
  }

  private void checkTargetMissing(DiagnosticsChecker diagnosticsChecker) {
    Field field;
    Method method;
    try {
      field = Target.class.getField("field");
      method = Target.class.getMethod("method", int.class);
    } catch (ReflectiveOperationException e) {
      throw new RuntimeException(e);
    }
    assertEquals(1, diagnosticsChecker.errors.size());
    assertEquals(0, diagnosticsChecker.warnings.size());
    assertEquals(0, diagnosticsChecker.infos.size());
    diagnosticsChecker.checkErrorsContains(Reference.classFromClass(Target.class).getTypeName());
    diagnosticsChecker.checkErrorsContains(
        FieldReferenceUtils.toSourceString(Reference.fieldFromField(field)));
    diagnosticsChecker.checkErrorsContains(
        MethodReferenceUtils.toSourceString(Reference.methodFromMethod(method)));
  }

  @Test
  public void testMissingReference_keepRules() throws Throwable {
    try {
      runAndCheckOutput(
          ImmutableList.of(OtherTarget.class),
          ImmutableList.of(Source.class),
          OutputFormat.KEEP_RULES,
          StringUtils.lines(),
          this::checkTargetMissing);
      fail("Expected compilation to fail");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void testMissingReference_keepRulesAllowObfuscation() throws Throwable {
    try {
      runAndCheckOutput(
          ImmutableList.of(OtherTarget.class),
          ImmutableList.of(Source.class),
          OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION,
          StringUtils.lines(),
          this::checkTargetMissing);
      fail("Expected compilation to fail");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void testMissingReference_errorToWarning() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar =
        zipWithTestClasses(dir.resolve("target.jar"), ImmutableList.of(OtherTarget.class));
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), ImmutableList.of(Source.class));
    DiagnosticsChecker diagnosticsChecker = new DiagnosticsChecker();
    TraceReferences.run(
        TraceReferencesCommand.parse(
                new String[] {
                  "--check",
                  "--lib",
                  ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
                  "--target",
                  targetJar.toString(),
                  "--source",
                  sourceJar.toString(),
                  "--map-diagnostics:MissingDefinitionsDiagnostic",
                  "error",
                  "warning"
                },
                Origin.unknown(),
                diagnosticsChecker)
            .build());
    assertEquals(0, diagnosticsChecker.errors.size());
    assertEquals(1, diagnosticsChecker.warnings.size());
    assertEquals(0, diagnosticsChecker.infos.size());
  }

  @Test
  public void testMissingReference_errorToWarningStdErr() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar =
        zipWithTestClasses(dir.resolve("target.jar"), ImmutableList.of(OtherTarget.class));
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), ImmutableList.of(Source.class));
    PrintStream originalErr = System.err;
    PrintStream originalOut = System.out;
    ByteArrayOutputStream baosErr = new ByteArrayOutputStream();
    ByteArrayOutputStream baosOut = new ByteArrayOutputStream();
    try {
      System.setErr(new PrintStream(baosErr));
      System.setOut(new PrintStream(baosOut));
      TraceReferences.run(
          TraceReferencesCommand.parse(
                  new String[] {
                    "--check",
                    "--lib",
                    ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
                    "--target",
                    targetJar.toString(),
                    "--source",
                    sourceJar.toString(),
                    "--map-diagnostics:MissingDefinitionsDiagnostic",
                    "error",
                    "warning"
                  },
                  Origin.unknown())
              .build());
    } finally {
      System.setErr(originalErr);
      System.setOut(originalOut);
    }

    DefinitionContext referencedFrom =
        DefinitionMethodContextImpl.builder()
            .setMethodContext(Reference.methodFromMethod(Source.class.getDeclaredMethod("source")))
            .setOrigin(getOrigin(Source.class))
            .build();
    assertThat(
        baosErr.toString(Charsets.UTF_8.name()),
        containsString(
            StringUtils.lines(
                "Warning: "
                    + getMissingClassMessage(
                        Reference.classFromClass(Target.class), referencedFrom),
                getMissingFieldMessage(
                    FieldReferenceUtils.fieldFromField(Target.class, "field"), referencedFrom),
                getMissingMethodMessage(
                    MethodReferenceUtils.methodFromMethod(Target.class, "method", int.class),
                    referencedFrom))));
    assertEquals(0, baosOut.size());
  }

  @Test
  public void testMissingReference_errorToInfoStdOut() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar =
        zipWithTestClasses(dir.resolve("target.jar"), ImmutableList.of(OtherTarget.class));
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), ImmutableList.of(Source.class));
    PrintStream originalErr = System.err;
    PrintStream originalOut = System.out;
    ByteArrayOutputStream baosErr = new ByteArrayOutputStream();
    ByteArrayOutputStream baosOut = new ByteArrayOutputStream();
    try {
      System.setErr(new PrintStream(baosErr));
      System.setOut(new PrintStream(baosOut));
      TraceReferences.run(
          TraceReferencesCommand.parse(
                  new String[] {
                    "--check",
                    "--lib",
                    ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
                    "--target",
                    targetJar.toString(),
                    "--source",
                    sourceJar.toString(),
                    "--map-diagnostics:MissingDefinitionsDiagnostic",
                    "error",
                    "info"
                  },
                  Origin.unknown())
              .build());
    } finally {
      System.setErr(originalErr);
      System.setOut(originalOut);
    }

    assertEquals(0, baosErr.size());

    DefinitionContext referencedFrom =
        DefinitionMethodContextImpl.builder()
            .setMethodContext(Reference.methodFromMethod(Source.class.getDeclaredMethod("source")))
            .setOrigin(getOrigin(Source.class))
            .build();
    assertThat(
        baosOut.toString(Charsets.UTF_8.name()),
        containsString(
            StringUtils.lines(
                "Info: "
                    + getMissingClassMessage(
                        Reference.classFromClass(Target.class), referencedFrom),
                getMissingFieldMessage(
                    FieldReferenceUtils.fieldFromField(Target.class, "field"), referencedFrom),
                getMissingMethodMessage(
                    MethodReferenceUtils.methodFromMethod(Target.class, "method", int.class),
                    referencedFrom))));
  }

  private void checkTargetPartlyMissing(DiagnosticsChecker diagnosticsChecker) {
    Field field;
    Method method;
    try {
      field = Target.class.getField("field");
      method = Target.class.getMethod("method", int.class);
    } catch (ReflectiveOperationException e) {
      throw new RuntimeException(e);
    }
    assertEquals(1, diagnosticsChecker.errors.size());
    assertEquals(0, diagnosticsChecker.warnings.size());
    assertEquals(0, diagnosticsChecker.infos.size());
    diagnosticsChecker.checkErrorsContains(
        FieldReferenceUtils.toSourceString(Reference.fieldFromField(field)));
    diagnosticsChecker.checkErrorsContains(
        MethodReferenceUtils.toSourceString(Reference.methodFromMethod(method)));
  }

  @Test
  public void testMissingDefinition_keepRules() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar =
        ZipBuilder.builder(dir.resolve("target.jar"))
            .addBytes(
                DescriptorUtils.getPathFromJavaType(Target.class), getClassWithTargetRemoved())
            .build();
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), ImmutableList.of(Source.class));
    try {
      runAndCheckOutput(
          targetJar,
          sourceJar,
          OutputFormat.KEEP_RULES,
          StringUtils.lines(
              ImmutableList.of(
                  "-keep class"
                      + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                      + " {",
                  "}",
                  "-keeppackagenames com.android.tools.r8.tracereferences")),
          this::checkTargetPartlyMissing);
      fail("Expected compilation to fail");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  @Test
  public void testMissingDefinition_keepRulesAllowObfuscation() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar =
        ZipBuilder.builder(dir.resolve("target.jar"))
            .addBytes(
                DescriptorUtils.getPathFromJavaType(Target.class), getClassWithTargetRemoved())
            .build();
    Path sourceJar = zipWithTestClasses(dir.resolve("source.jar"), ImmutableList.of(Source.class));
    try {
      runAndCheckOutput(
          targetJar,
          sourceJar,
          OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION,
          StringUtils.lines(
              ImmutableList.of(
                  "-keep,allowobfuscation class"
                      + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target {",
                  "}",
                  "-keeppackagenames com.android.tools.r8.tracereferences")),
          this::checkTargetPartlyMissing);
      fail("Expected compilation to fail");
    } catch (CompilationFailedException e) {
      // Expected.
    }
  }

  private byte[] getClassWithTargetRemoved() throws IOException {
    return transformer(Target.class)
        .removeMethods((access, name, descriptor, signature, exceptions) -> name.equals("method"))
        .removeFields((access, name, descriptor, signature, value) -> name.equals("field"))
        .transform();
  }

  static class Target {
    public static int field;

    public static void method(int i) {}
  }

  static class OtherTarget {
    public static void method() {}
  }

  static class Source {
    public static void source() {
      Target.method(Target.field);
    }
  }
}
