blob: 20e2bd4a874e4840dc9cb9017af19c3010bb043f [file] [log] [blame]
// Copyright (c) 2023, 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.compilerapi.extractmarker;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringStartsWith.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.ExtractMarker;
import com.android.tools.r8.ExtractMarkerCommand;
import com.android.tools.r8.MarkerInfo;
import com.android.tools.r8.MarkerInfoConsumer;
import com.android.tools.r8.MarkerInfoConsumerData;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.compilerapi.CompilerApiTest;
import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.IntBox;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
import org.junit.Test;
public class ExtractMarkerApiTest extends CompilerApiTestRunner {
public ExtractMarkerApiTest(TestParameters parameters) {
super(parameters);
}
@Override
public Class<? extends CompilerApiTest> binaryTestClass() {
return ApiTest.class;
}
public static class SomeClass {}
public static class SomeOrigin extends Origin {
private final String name;
public SomeOrigin(String name) {
super(Origin.root());
this.name = name;
}
@Override
public String part() {
return name;
}
}
@Test
public void test() throws Exception {
Path inputFile = ToolHelper.getClassFileForTestClass(SomeClass.class);
byte[] inputCf = ToolHelper.getClassAsBytes(SomeClass.class);
Box<byte[]> inputDex = new Box<>();
// Compile DEX code for use as byte input.
testForD8(Backend.DEX)
.addProgramClasses(SomeClass.class)
.setMinApi(1)
.setProgramConsumer(
new DexIndexedConsumer() {
byte[] bytes = null;
@Override
public void accept(
int fileIndex,
ByteDataView data,
Set<String> descriptors,
DiagnosticsHandler handler) {
assertEquals(0, fileIndex);
assertNull(bytes);
bytes = data.copyByteData();
}
@Override
public void finished(DiagnosticsHandler handler) {
assertNotNull(bytes);
inputDex.set(bytes);
}
})
.compile();
assertNotNull(inputDex.get());
Origin originDex = new SomeOrigin("dex bytes");
Origin originCf = new SomeOrigin("cf bytes");
IntBox calls = new IntBox(0);
new ApiTest(ApiTest.PARAMETERS)
.run(
inputFile,
inputDex.get(),
originDex,
inputCf,
originCf,
(origin, marker) -> {
calls.increment();
if (origin == originDex) {
assertEquals("D8", marker.getTool());
assertTrue(marker.isD8());
assertFalse(marker.isR8());
assertFalse(marker.isL8());
assertEquals(1, marker.getMinApi());
assertThat(marker.getRawEncoding(), startsWith("~~D8{"));
} else {
assertTrue(origin == originCf || origin.equals(new PathOrigin(inputFile)));
// The CF input file and bytes have no marker as they are javac generated.
assertNull(marker);
}
});
assertEquals(4, calls.get());
}
public static class ApiTest extends CompilerApiTest {
public ApiTest(Object parameters) {
super(parameters);
}
public void run(
Path inputFile,
byte[] inputDex,
Origin dexOrigin,
byte[] inputCf,
Origin cfOrigin,
BiConsumer<Origin, MarkerInfo> consumer)
throws Exception {
ExtractMarkerCommand.Builder builder = ExtractMarkerCommand.builder();
if (inputFile != null) {
builder.addProgramFiles(inputFile).addProgramFiles(Collections.singleton(inputFile));
}
if (inputDex != null) {
builder.addDexProgramData(inputDex, dexOrigin);
}
if (inputCf != null) {
builder.addClassProgramData(inputCf, cfOrigin);
}
builder.setMarkerInfoConsumer(
new MarkerInfoConsumer() {
@Override
public void acceptMarkerInfo(MarkerInfoConsumerData data) {
if (data.hasMarkers()) {
data.getMarkers()
.forEach(
marker -> {
consumer.accept(data.getInputOrigin(), marker);
});
} else {
consumer.accept(data.getInputOrigin(), null);
}
}
@Override
public void finished() {}
});
ExtractMarker.run(builder.build());
}
@Test
public void test() throws Exception {
byte[] inputCf = getBytesForClass(getMockClass());
run(
null,
null,
null,
inputCf,
Origin.root(),
(origin, marker) -> {
// Marker is null here but use all currently defined methods on marker info to force
// binary compatible usage.
if (marker != null) {
String tool = marker.getTool();
boolean d8 = marker.isD8();
boolean r8 = marker.isR8();
boolean l8 = marker.isL8();
int minApi = marker.getMinApi();
String raw = marker.getRawEncoding();
}
});
}
}
}