|  | // 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.shaking; | 
|  |  | 
|  | import static org.hamcrest.CoreMatchers.containsString; | 
|  | import static org.hamcrest.MatcherAssert.assertThat; | 
|  | import static org.junit.Assert.assertEquals; | 
|  | import static org.junit.Assert.assertNotEquals; | 
|  |  | 
|  | import com.android.tools.r8.DexIndexedConsumer; | 
|  | import com.android.tools.r8.OutputMode; | 
|  | import com.android.tools.r8.R8Command; | 
|  | import com.android.tools.r8.TestBase; | 
|  | import com.android.tools.r8.ToolHelper; | 
|  | import com.android.tools.r8.ToolHelper.ProcessResult; | 
|  | import com.android.tools.r8.origin.Origin; | 
|  | import com.android.tools.r8.utils.AndroidApp; | 
|  | import com.google.common.collect.ImmutableList; | 
|  | import java.nio.file.Path; | 
|  | import java.util.List; | 
|  | import org.junit.Before; | 
|  | import org.junit.Test; | 
|  |  | 
|  | interface GoingToBeMissed { | 
|  | void onSomeEvent(long soLong); | 
|  | } | 
|  |  | 
|  | class TestClassForB112849320 { | 
|  | GoingToBeMissed instance; | 
|  | void foo(GoingToBeMissed instance) { | 
|  | System.out.println("B112849320"); | 
|  | this.instance = instance; | 
|  | } | 
|  |  | 
|  | void bar() { | 
|  | instance.onSomeEvent(8L); | 
|  | } | 
|  |  | 
|  | public static void main(String[] args) { | 
|  | TestClassForB112849320 self = new TestClassForB112849320(); | 
|  | self.foo(l -> { | 
|  | if (l > 0) { | 
|  | System.out.println(l); | 
|  | } | 
|  | }); | 
|  | self.bar(); | 
|  | } | 
|  | } | 
|  |  | 
|  | public class MissingInterfaceTest extends TestBase { | 
|  | private static String MAIN_NAME = TestClassForB112849320.class.getCanonicalName(); | 
|  | private Path libJar; | 
|  | private Path libDex; | 
|  |  | 
|  | @Before | 
|  | public void setUp() throws Exception { | 
|  | libJar = writeToJar(ImmutableList.of(ToolHelper.getClassAsBytes(GoingToBeMissed.class))); | 
|  | libDex = temp.getRoot().toPath().resolve("lib.zip"); | 
|  | AndroidApp libApp = ToolHelper.runD8(readClasses(GoingToBeMissed.class)); | 
|  | libApp.writeToZip(libDex, OutputMode.DexIndexed); | 
|  | } | 
|  |  | 
|  | @Test | 
|  | public void test_missingInterface() throws Exception { | 
|  | List<String> config = ImmutableList.of( | 
|  | "-printmapping", | 
|  | "-keep class " + MAIN_NAME + " {", | 
|  | "  public static void main(...);", | 
|  | "}" | 
|  | ); | 
|  | R8Command.Builder builder = R8Command.builder(); | 
|  | builder.addProgramFiles(ToolHelper.getClassFileForTestClass(TestClassForB112849320.class)); | 
|  | builder.addLibraryFiles(ToolHelper.getDefaultAndroidJar()); | 
|  | builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer()); | 
|  | builder.setMinApiLevel(ToolHelper.getMinApiLevelForDexVm().getLevel()); | 
|  | builder.addProguardConfiguration(config, Origin.unknown()); | 
|  | AndroidApp processedApp = ToolHelper.runR8(builder.build(), options -> { | 
|  | options.enableInlining = false; | 
|  | }); | 
|  |  | 
|  | Path outDex = temp.getRoot().toPath().resolve("dex.zip"); | 
|  | processedApp.writeToZip(outDex, OutputMode.DexIndexed); | 
|  | ProcessResult artResult = ToolHelper.runArtRaw( | 
|  | ImmutableList.of(outDex.toString(), libDex.toString()), MAIN_NAME, null); | 
|  | assertNotEquals(0, artResult.exitCode); | 
|  | assertThat(artResult.stdout, containsString("B112849320")); | 
|  | assertNotEquals(-1, artResult.stderr.indexOf("AbstractMethodError")); | 
|  | } | 
|  |  | 
|  | @Test | 
|  | public void test_passingInterfaceAsLib() throws Exception { | 
|  | List<String> config = ImmutableList.of( | 
|  | "-printmapping", | 
|  | "-keep class " + MAIN_NAME + " {", | 
|  | "  public static void main(...);", | 
|  | "}" | 
|  | ); | 
|  | R8Command.Builder builder = R8Command.builder(); | 
|  | builder.addProgramFiles(ToolHelper.getClassFileForTestClass(TestClassForB112849320.class)); | 
|  | builder.addLibraryFiles(ToolHelper.getDefaultAndroidJar(), libJar); | 
|  | builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer()); | 
|  | builder.setMinApiLevel(ToolHelper.getMinApiLevelForDexVm().getLevel()); | 
|  | builder.addProguardConfiguration(config, Origin.unknown()); | 
|  | AndroidApp processedApp = ToolHelper.runR8(builder.build(), options -> { | 
|  | options.enableInlining = false; | 
|  | }); | 
|  |  | 
|  | Path outDex = temp.getRoot().toPath().resolve("dex.zip"); | 
|  | processedApp.writeToZip(outDex, OutputMode.DexIndexed); | 
|  | ProcessResult artResult = ToolHelper.runArtRaw( | 
|  | ImmutableList.of(outDex.toString(), libDex.toString()), MAIN_NAME, null); | 
|  | assertEquals(0, artResult.exitCode); | 
|  | assertThat(artResult.stdout, containsString("B112849320")); | 
|  | assertEquals(-1, artResult.stderr.indexOf("AbstractMethodError")); | 
|  | } | 
|  |  | 
|  | } |