blob: 13ebc956abc66d56afcc55c8c5ed8e0a38608009 [file] [log] [blame]
// 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.repackage;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DataResourceConsumerForTesting;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import java.util.List;
import java.util.ServiceLoader;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class RepackageWithServiceLoaderTest extends RepackageTestBase {
public RepackageWithServiceLoaderTest(
String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
super(flattenPackageHierarchyOrRepackageClasses, parameters);
}
@Test
public void test() throws Exception {
Box<DataResourceConsumerForTesting> dataResourceConsumer = new Box<>();
R8TestRunResult runResult =
testForR8(parameters.getBackend())
.addInnerClasses(getClass())
.addDataEntryResources(
DataEntryResource.fromBytes(
StringUtils.lines(ServiceImpl.class.getTypeName()).getBytes(),
"META-INF/services/" + Service.class.getTypeName(),
Origin.unknown()))
.addKeepMainRule(TestClass.class)
.addOptionsModification(
options -> {
dataResourceConsumer.set(
new DataResourceConsumerForTesting(options.dataResourceConsumer));
options.dataResourceConsumer = dataResourceConsumer.get();
})
.apply(this::configureRepackaging)
.setMinApi(parameters.getApiLevel())
.compile()
.inspect(this::inspect)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutputLines("Hello world!");
CodeInspector inspector = runResult.inspector();
ClassSubject testClassSubject = inspector.clazz(TestClass.class);
assertThat(testClassSubject, isPresent());
assertTrue(
testClassSubject
.mainMethod()
.streamInstructions()
.filter(InstructionSubject::isInvokeStatic)
.map(InstructionSubject::getMethod)
.anyMatch(
method ->
method
.toSourceString()
.equals(
"java.util.ServiceLoader"
+ " java.util.ServiceLoader.load(java.lang.Class)")));
ClassSubject serviceClassSubject = inspector.clazz(Service.class);
assertThat(serviceClassSubject, isPresent());
ClassSubject serviceImplClassSubject = inspector.clazz(ServiceImpl.class);
assertThat(serviceImplClassSubject, isPresent());
inspectResource(
dataResourceConsumer.get().get("META-INF/services/" + serviceClassSubject.getFinalName()),
serviceImplClassSubject);
}
private void inspectResource(List<String> contents, ClassSubject serviceImplClassSubject) {
assertNotNull(contents);
assertEquals(1, contents.size());
assertEquals(serviceImplClassSubject.getFinalName(), contents.get(0));
}
private void inspect(CodeInspector inspector) {
assertThat(Service.class, isRepackaged(inspector));
assertThat(ServiceImpl.class, isRepackaged(inspector));
}
public static class TestClass {
public static void main(String[] args) {
for (Service service : ServiceLoader.load(getServiceClass())) {
service.greet();
}
}
static Class<? extends Service> getServiceClass() {
return System.currentTimeMillis() > 0 ? Service.class : ServiceImpl.class;
}
}
public interface Service {
void greet();
}
public static class ServiceImpl implements Service {
@Override
public void greet() {
System.out.println("Hello world!");
}
}
}