// 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.shaking.forceproguardcompatibility;

import static com.android.tools.r8.references.Reference.classFromClass;
import static com.android.tools.r8.references.Reference.methodFromMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.onlyIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.R8CompatTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.shaking.forceproguardcompatibility.TestMain.MentionedClass;
import com.android.tools.r8.shaking.forceproguardcompatibility.defaultmethods.ClassImplementingInterface;
import com.android.tools.r8.shaking.forceproguardcompatibility.defaultmethods.InterfaceWithDefaultMethods;
import com.android.tools.r8.shaking.forceproguardcompatibility.defaultmethods.TestClass;
import com.android.tools.r8.shaking.forceproguardcompatibility.keepattributes.TestKeepAttributes;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.android.tools.r8.utils.graphinspector.GraphInspector;
import com.android.tools.r8.utils.graphinspector.GraphInspector.QueryNode;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
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 ForceProguardCompatibilityTest extends TestBase {

  private final TestParameters parameters;
  private final boolean forceProguardCompatibility;

  @Parameters(name = "{0}, compat:{1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters()
            .withAllRuntimes()
            .withApiLevelsStartingAtIncluding(AndroidApiLevel.O)
            .build(),
        BooleanUtils.values());
  }

  public ForceProguardCompatibilityTest(
      TestParameters parameters, boolean forceProguardCompatibility) {
    this.parameters = parameters;
    this.forceProguardCompatibility = forceProguardCompatibility;
  }

  private void test(Class<?> mainClass, Class<?> mentionedClass) throws Exception {
    test(mainClass, mentionedClass, null);
  }

  private void test(
      Class<?> mainClass,
      Class<?> mentionedClass,
      ThrowableConsumer<R8CompatTestBuilder> configuration)
      throws Exception {
    CodeInspector inspector =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addDontObfuscate()
            .allowAccessModification()
            .addProgramClasses(mainClass, mentionedClass)
            .addKeepMainRule(mainClass)
            .apply(configuration)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspector();
    assertThat(inspector.clazz(mainClass), isPresent());
    ClassSubject clazz = inspector.clazz(mentionedClass);
    assertThat(clazz, isPresent());
    MethodSubject defaultInitializer = clazz.method(MethodSignature.initializer(new String[]{}));
    assertEquals(forceProguardCompatibility, defaultInitializer.isPresent());
  }

  @Test
  public void testKeepDefaultInitializer() throws Exception {
    test(
        TestMain.class,
        TestMain.MentionedClass.class,
        testBuilder ->
            testBuilder.addProgramClasses(
                TestMain.MentionedClassWithAnnotation.class, TestAnnotation.class));
  }

  @Test
  public void testKeepDefaultInitializerArrayType() throws Exception {
    test(TestMainArrayType.class, TestMainArrayType.MentionedClass.class);
  }

  private void runAnnotationsTest(boolean keepAnnotations) throws Exception {
    // Add application classes including the annotation class.
    Class<?> mainClass = TestMain.class;
    Class<?> mentionedClassWithAnnotations = TestMain.MentionedClassWithAnnotation.class;
    Class<?> annotationClass = TestAnnotation.class;

    CodeInspector inspector =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addProgramClasses(
                mainClass, MentionedClass.class, mentionedClassWithAnnotations, annotationClass)
            .addKeepMainRule(mainClass)
            .allowAccessModification()
            .addKeepClassAndMembersRules(annotationClass)
            .map(b -> keepAnnotations ? b.addKeepAttributes("*Annotation*") : b)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspector();

    assertThat(inspector.clazz(mainClass), isPresent());
    ClassSubject clazz = inspector.clazz(mentionedClassWithAnnotations);
    assertThat(clazz, isPresent());

    // The test contains only a member class so the enclosing-method attribute will be null.
    assertTrue(clazz.getDexProgramClass().getInnerClasses().isEmpty());

    if (keepAnnotations) {
      assertThat(
          clazz.annotation(annotationClass.getCanonicalName()),
          onlyIf(forceProguardCompatibility, isPresent()));
    } else {
      assertThat(clazz.annotation(annotationClass.getCanonicalName()), isAbsent());
    }
  }

  @Test
  public void testAnnotations() throws Exception {
    runAnnotationsTest(true);
    runAnnotationsTest(false);
  }

  private void runDefaultConstructorTest(Class<?> testClass, boolean hasDefaultConstructor)
      throws Exception {

    List<String> proguardConfig = ImmutableList.of(
        "-keep class " + testClass.getCanonicalName() + " {",
        "  public void method();",
        "}");

    GraphInspector inspector =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addProgramClasses(testClass)
            .addKeepRules(proguardConfig)
            .enableGraphInspector()
            .setMinApi(parameters.getApiLevel())
            .compile()
            .graphInspector();

    QueryNode clazzNode = inspector.clazz(classFromClass(testClass)).assertPresent();
    if (hasDefaultConstructor) {
      QueryNode initNode = inspector.method(methodFromMethod(testClass.getConstructor()));
      if (forceProguardCompatibility) {
        initNode.assertPureCompatKeptBy(clazzNode);
      } else {
        initNode.assertAbsent();
      }
    }

    if (isRunProguard()) {
      Path proguardedJar = File.createTempFile("proguarded", ".jar", temp.getRoot()).toPath();
      Path proguardConfigFile = File.createTempFile("proguard", ".config", temp.getRoot()).toPath();
      Path proguardMapFile = File.createTempFile("proguard", ".map", temp.getRoot()).toPath();
      FileUtils.writeTextFile(proguardConfigFile, proguardConfig);
      ToolHelper.runProguard(jarTestClasses(testClass),
          proguardedJar, proguardConfigFile, proguardMapFile);
    }
  }

  @Test
  public void testDefaultConstructor() throws Exception {
    runDefaultConstructorTest(TestClassWithDefaultConstructor.class, true);
    runDefaultConstructorTest(TestClassWithoutDefaultConstructor.class, false);
  }

  public void testCheckCast(
      Class<?> mainClass, Class<?> instantiatedClass, boolean containsCheckCast) throws Exception {
    List<String> proguardConfig =
        ImmutableList.of(
            "-keep class " + mainClass.getTypeName() + " {",
            "  public static void main(java.lang.String[]);",
            "}",
            "-dontobfuscate");

    CodeInspector inspector =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addProgramClasses(mainClass, instantiatedClass)
            .addKeepRules(proguardConfig)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspector();

    assertTrue(inspector.clazz(mainClass).isPresent());
    ClassSubject clazz = inspector.clazz(instantiatedClass);
    assertEquals(containsCheckCast, clazz.isPresent());
    if (clazz.isPresent()) {
      assertEquals(forceProguardCompatibility && containsCheckCast, !clazz.isAbstract());
    }

    if (isRunProguard()) {
      Path proguardedJar = File.createTempFile("proguarded", ".jar", temp.getRoot()).toPath();
      Path proguardConfigFile = File.createTempFile("proguard", ".config", temp.getRoot()).toPath();
      FileUtils.writeTextFile(proguardConfigFile, proguardConfig);
      ToolHelper.runProguard(jarTestClasses(ImmutableList.of(mainClass, instantiatedClass)),
          proguardedJar, proguardConfigFile, null);
      CodeInspector proguardInspector = new CodeInspector(readJar(proguardedJar));
      assertTrue(proguardInspector.clazz(mainClass).isPresent());
      assertEquals(
          containsCheckCast, proguardInspector.clazz(instantiatedClass).isPresent());
    }
  }

  @Test
  public void checkCastTest() throws Exception {
    testCheckCast(
        TestMainWithCheckCast.class,
        TestClassWithDefaultConstructor.class,
        forceProguardCompatibility);
    testCheckCast(TestMainWithoutCheckCast.class, TestClassWithDefaultConstructor.class, false);
  }

  public void testClassForName(boolean allowObfuscation) throws Exception {
    Class<?> mainClass = TestMainWithClassForName.class;
    Class<?> forNameClass1 = TestClassWithDefaultConstructor.class;
    Class<?> forNameClass2 = TestClassWithoutDefaultConstructor.class;
    List<Class<?>> forNameClasses = ImmutableList.of(forNameClass1, forNameClass2);
    ImmutableList.Builder<String> proguardConfigurationBuilder = ImmutableList.builder();
    proguardConfigurationBuilder.add(
        "-keep class " + mainClass.getCanonicalName() + " {",
        "  <init>();",  // Add <init>() so it does not become a compatibility rule below.
        "  public static void main(java.lang.String[]);",
        "}");
    if (!allowObfuscation) {
      proguardConfigurationBuilder.add("-dontobfuscate");
    }
    List<String> proguardConfig = proguardConfigurationBuilder.build();

    CodeInspector inspector =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addProgramClasses(mainClass, forNameClass1, forNameClass2)
            .addKeepRules(proguardConfig)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspector();

    assertTrue(inspector.clazz(mainClass).isPresent());
    forNameClasses.forEach(
        clazz -> {
          ClassSubject subject = inspector.clazz(clazz);
          assertTrue(subject.isPresent());
          assertEquals(allowObfuscation, subject.isRenamed());
        });

    if (isRunProguard()) {
      Path proguardedJar = File.createTempFile("proguarded", ".jar", temp.getRoot()).toPath();
      Path proguardConfigFile = File.createTempFile("proguard", ".config", temp.getRoot()).toPath();
      Path proguardMapFile = File.createTempFile("proguard", ".map", temp.getRoot()).toPath();
      FileUtils.writeTextFile(proguardConfigFile, proguardConfig);
      ToolHelper.runProguard(jarTestClasses(
          ImmutableList.of(mainClass, forNameClass1, forNameClass2)),
          proguardedJar, proguardConfigFile, proguardMapFile);
      CodeInspector proguardedInspector = new CodeInspector(readJar(proguardedJar), proguardMapFile);
      assertEquals(3, proguardedInspector.allClasses().size());
      assertTrue(proguardedInspector.clazz(mainClass).isPresent());
      for (Class<?> clazz : ImmutableList.of(forNameClass1, forNameClass2)) {
        assertTrue(proguardedInspector.clazz(clazz).isPresent());
        assertEquals(allowObfuscation, proguardedInspector.clazz(clazz).isRenamed());
      }
    }
  }

  @Test
  public void classForNameTest() throws Exception {
    testClassForName(true);
    testClassForName(false);
  }

  public void testClassGetMembers(boolean allowObfuscation) throws Exception {
    Class<?> mainClass = TestMainWithGetMembers.class;
    Class<?> withMemberClass = TestClassWithMembers.class;

    ImmutableList.Builder<String> proguardConfigurationBuilder = ImmutableList.builder();
    proguardConfigurationBuilder.add(
        "-keep class " + mainClass.getCanonicalName() + " {",
        "  <init>();",  // Add <init>() so it does not become a compatibility rule below.
        "  public static void main(java.lang.String[]);",
        "}");
    if (!allowObfuscation) {
      proguardConfigurationBuilder.add("-dontobfuscate");
    }
    List<String> proguardConfig = proguardConfigurationBuilder.build();

    CodeInspector inspector =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addProgramClasses(mainClass, withMemberClass)
            .addKeepRules(proguardConfig)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspector();

    assertTrue(inspector.clazz(mainClass).isPresent());
    ClassSubject classSubject = inspector.clazz(withMemberClass);
    // Due to the direct usage of .class
    assertTrue(classSubject.isPresent());
    assertEquals(allowObfuscation, classSubject.isRenamed());
    FieldSubject foo = classSubject.field("java.lang.String", "foo");
    assertTrue(foo.isPresent());
    assertEquals(allowObfuscation, foo.isRenamed());
    MethodSubject bar =
        classSubject.method("java.lang.String", "bar", ImmutableList.of("java.lang.String"));
    assertTrue(bar.isPresent());
    assertEquals(allowObfuscation, bar.isRenamed());

    if (isRunProguard()) {
      Path proguardedJar = File.createTempFile("proguarded", ".jar", temp.getRoot()).toPath();
      Path proguardConfigFile = File.createTempFile("proguard", ".config", temp.getRoot()).toPath();
      Path proguardMapFile = File.createTempFile("proguard", ".map", temp.getRoot()).toPath();
      FileUtils.writeTextFile(proguardConfigFile, proguardConfig);
      ToolHelper.runProguard(jarTestClasses(
          ImmutableList.of(mainClass, withMemberClass)),
          proguardedJar, proguardConfigFile, proguardMapFile);
      CodeInspector proguardedInspector = new CodeInspector(readJar(proguardedJar), proguardMapFile);
      assertEquals(2, proguardedInspector.allClasses().size());
      assertTrue(proguardedInspector.clazz(mainClass).isPresent());
      classSubject = proguardedInspector.clazz(withMemberClass);
      assertTrue(classSubject.isPresent());
      assertEquals(allowObfuscation, classSubject.isRenamed());
      foo = classSubject.field("java.lang.String", "foo");
      assertTrue(foo.isPresent());
      assertEquals(allowObfuscation, foo.isRenamed());
      bar = classSubject.method("java.lang.String", "bar", ImmutableList.of("java.lang.String"));
      assertTrue(bar.isPresent());
      assertEquals(allowObfuscation, bar.isRenamed());
    }
  }

  @Test
  public void classGetMembersTest() throws Exception {
    testClassGetMembers(true);
    testClassGetMembers(false);
  }

  public void testAtomicFieldUpdaters(boolean allowObfuscation) throws Exception {
    Class<?> mainClass = TestMainWithAtomicFieldUpdater.class;
    Class<?> withVolatileFields = TestClassWithVolatileFields.class;

    ImmutableList.Builder<String> proguardConfigurationBuilder = ImmutableList.builder();
    proguardConfigurationBuilder.add(
        "-keep class " + mainClass.getCanonicalName() + " {",
        "  <init>();",  // Add <init>() so it does not become a compatibility rule below.
        "  public static void main(java.lang.String[]);",
        "}");
    if (!allowObfuscation) {
      proguardConfigurationBuilder.add("-dontobfuscate");
    }
    List<String> proguardConfig = proguardConfigurationBuilder.build();

    CodeInspector inspector =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addProgramClasses(mainClass, withVolatileFields)
            .addKeepRules(proguardConfig)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspector();

    assertTrue(inspector.clazz(mainClass).isPresent());
    ClassSubject classSubject = inspector.clazz(withVolatileFields);
    // Due to the direct usage of .class
    assertTrue(classSubject.isPresent());
    assertEquals(allowObfuscation, classSubject.isRenamed());
    FieldSubject f = classSubject.field("int", "intField");
    assertTrue(f.isPresent());
    assertEquals(allowObfuscation, f.isRenamed());
    f = classSubject.field("long", "longField");
    assertTrue(f.isPresent());
    assertEquals(allowObfuscation, f.isRenamed());
    f = classSubject.field("java.lang.Object", "objField");
    assertTrue(f.isPresent());
    assertEquals(allowObfuscation, f.isRenamed());

    if (isRunProguard()) {
      Path proguardedJar = File.createTempFile("proguarded", ".jar", temp.getRoot()).toPath();
      Path proguardConfigFile = File.createTempFile("proguard", ".config", temp.getRoot()).toPath();
      Path proguardMapFile = File.createTempFile("proguard", ".map", temp.getRoot()).toPath();
      FileUtils.writeTextFile(proguardConfigFile, proguardConfig);
      ToolHelper.runProguard(jarTestClasses(
          ImmutableList.of(mainClass, withVolatileFields)),
          proguardedJar, proguardConfigFile, proguardMapFile);
      CodeInspector proguardedInspector = new CodeInspector(readJar(proguardedJar), proguardMapFile);
      assertEquals(2, proguardedInspector.allClasses().size());
      assertTrue(proguardedInspector.clazz(mainClass).isPresent());
      classSubject = proguardedInspector.clazz(withVolatileFields);
      assertTrue(classSubject.isPresent());
      assertEquals(allowObfuscation, classSubject.isRenamed());
      f = classSubject.field("int", "intField");
      assertTrue(f.isPresent());
      assertEquals(allowObfuscation, f.isRenamed());
      f = classSubject.field("long", "longField");
      assertTrue(f.isPresent());
      assertEquals(allowObfuscation, f.isRenamed());
      f = classSubject.field("java.lang.Object", "objField");
      assertTrue(f.isPresent());
      assertEquals(allowObfuscation, f.isRenamed());
    }
  }

  @Test
  public void atomicFieldUpdaterTest() throws Exception {
    testAtomicFieldUpdaters(true);
    testAtomicFieldUpdaters(false);
  }

  public void testKeepAttributes(boolean innerClasses, boolean enclosingMethod) throws Exception {
    String keepRules = "";
    if (innerClasses || enclosingMethod) {
      List<String> attributes = new ArrayList<>();
      if (innerClasses) {
        attributes.add(ProguardKeepAttributes.INNER_CLASSES);
      }
      if (enclosingMethod) {
        attributes.add(ProguardKeepAttributes.ENCLOSING_METHOD);
      }
      keepRules = "-keepattributes " + String.join(",", attributes);
    }
    CodeInspector inspector;

    try {
      inspector =
          testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
              .addProgramFiles(
                  ToolHelper.getClassFilesForTestPackage(TestKeepAttributes.class.getPackage()))
              .addKeepRules(
                  "-keep class " + TestKeepAttributes.class.getTypeName() + " {",
                  "  <init>();", // Add <init>() so it does not become a compatibility rule below.
                  "  public static void main(java.lang.String[]);",
                  "}",
                  keepRules)
              .addOptionsModification(options -> options.enableClassInlining = false)
              .enableSideEffectAnnotations()
              .setMinApi(parameters.getApiLevel())
              .run(parameters.getRuntime(), TestKeepAttributes.class)
              .applyIf(
                  forceProguardCompatibility && (innerClasses || enclosingMethod),
                  result -> result.assertSuccessWithOutput("1"))
              .applyIf(
                  !forceProguardCompatibility || !(innerClasses || enclosingMethod),
                  result -> result.assertSuccessWithOutput("0"))
              .inspector();
    } catch (CompilationFailedException e) {
      assertTrue(!forceProguardCompatibility && (!innerClasses || !enclosingMethod));
      return;
    }

    ClassSubject clazz = inspector.clazz(TestKeepAttributes.class);
    assertThat(clazz, isPresent());
    if (forceProguardCompatibility && (innerClasses || enclosingMethod)) {
      assertFalse(clazz.getDexProgramClass().getInnerClasses().isEmpty());
    } else {
      assertTrue(clazz.getDexProgramClass().getInnerClasses().isEmpty());
    }
  }

  @Test
  public void keepAttributesTest() throws Exception {
    testKeepAttributes(false, false);
    testKeepAttributes(true, false);
    testKeepAttributes(false, true);
    testKeepAttributes(true, true);
  }

  private void runKeepDefaultMethodsTest(
      List<String> additionalKeepRules,
      Consumer<CodeInspector> inspection,
      Consumer<GraphInspector> compatInspection)
      throws Exception {
    if (parameters.isDexRuntime()) {
      assert parameters.getApiLevel().getLevel() >= AndroidApiLevel.O.getLevel();
    }

    Class<?> mainClass = TestClass.class;
    R8TestCompileResult compileResult =
        testForR8Compat(parameters.getBackend(), forceProguardCompatibility)
            .addProgramFiles(ToolHelper.getClassFilesForTestPackage(mainClass.getPackage()))
            .addKeepRules(
                "-keep class " + mainClass.getCanonicalName() + "{",
                "  public <init>();",
                "  public static void main(java.lang.String[]);",
                "}",
                "-dontobfuscate")
            .addKeepRules(additionalKeepRules)
            .enableGraphInspector()
            .setMinApi(parameters.getApiLevel())
            .addOptionsModification(
                o -> {
                  o.enableClassInlining = false;

                  // Prevent InterfaceWithDefaultMethods from being merged into
                  // ClassImplementingInterface.
                  o.enableVerticalClassMerging = false;
                })
            .compile();
    inspection.accept(compileResult.inspector());
    compatInspection.accept(compileResult.graphInspector());
  }

  private void noCompatibilityRules(GraphInspector inspector) {
    inspector.assertNoPureCompatibilityEdges();
  }

  private void defaultMethodKept(CodeInspector inspector) {
    ClassSubject clazz = inspector.clazz(InterfaceWithDefaultMethods.class);
    assertTrue(clazz.isPresent());
    MethodSubject method = clazz.method("int", "method", ImmutableList.of());
    assertTrue(method.isPresent());
    assertFalse(method.isAbstract());
  }

  private void defaultMethodCompatibilityRules(GraphInspector inspector) {
    // The enqueuer does not add an edge for the referenced => kept edges so we cant check compat.
  }

  private void defaultMethod2Kept(CodeInspector inspector) {
    ClassSubject clazz = inspector.clazz(InterfaceWithDefaultMethods.class);
    assertTrue(clazz.isPresent());
    MethodSubject method =
        clazz.method("void", "method2", ImmutableList.of("java.lang.String", "int"));
    assertTrue(method.isPresent());
    assertFalse(method.isAbstract());
  }

  private void defaultMethod2CompatibilityRules(GraphInspector inspector) {
    // The enqueuer does not add an edge for the referenced => kept edges so we cant check compat.
  }

  @Test
  public void keepDefaultMethodsTest() throws Exception {
    assumeTrue(forceProguardCompatibility);
    runKeepDefaultMethodsTest(ImmutableList.of(
        "-keep interface " + InterfaceWithDefaultMethods.class.getCanonicalName() + "{",
        "  public int method();",
        "}"
    ), this::defaultMethodKept, this::noCompatibilityRules);
    runKeepDefaultMethodsTest(ImmutableList.of(
        "-keep class " + ClassImplementingInterface.class.getCanonicalName() + "{",
        "  <methods>;",
        "}",
        "-keep class " + TestClass.class.getCanonicalName() + "{",
        "  public void useInterfaceMethod();",
        "}"
    ), this::defaultMethodKept, this::defaultMethodCompatibilityRules);
    runKeepDefaultMethodsTest(ImmutableList.of(
        "-keep class " + ClassImplementingInterface.class.getCanonicalName() + "{",
        "  <methods>;",
        "}",
        "-keep class " + TestClass.class.getCanonicalName() + "{",
        "  public void useInterfaceMethod2();",
        "}"
    ), this::defaultMethod2Kept, this::defaultMethod2CompatibilityRules);
  }
}
