| // 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; |
| |
| import com.android.tools.r8.ProgramResource.Kind; |
| import com.android.tools.r8.ToolHelper.ProcessResult; |
| import com.android.tools.r8.debug.CfDebugTestConfig; |
| import com.android.tools.r8.debug.DebugTestConfig; |
| import com.android.tools.r8.errors.Unimplemented; |
| import com.android.tools.r8.origin.Origin; |
| import com.android.tools.r8.origin.PathOrigin; |
| import com.android.tools.r8.utils.AndroidApp; |
| import com.android.tools.r8.utils.DescriptorUtils; |
| import com.android.tools.r8.utils.FileUtils; |
| import com.android.tools.r8.utils.ListUtils; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Set; |
| |
| public class JvmTestBuilder extends TestBuilder<JvmTestRunResult, JvmTestBuilder> { |
| |
| private static class ClassFileResource implements ProgramResource { |
| |
| private final Path file; |
| private final String descriptor; |
| private final Origin origin; |
| |
| ClassFileResource(Class<?> clazz) { |
| this( |
| ToolHelper.getClassFileForTestClass(clazz), |
| DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName())); |
| } |
| |
| ClassFileResource(Path file, String descriptor) { |
| this.file = file; |
| this.descriptor = descriptor; |
| origin = new PathOrigin(file); |
| } |
| |
| @Override |
| public Kind getKind() { |
| return Kind.CF; |
| } |
| |
| @Override |
| public InputStream getByteStream() throws ResourceException { |
| try { |
| return Files.newInputStream(file); |
| } catch (IOException e) { |
| throw new ResourceException(getOrigin(), e); |
| } |
| } |
| |
| @Override |
| public Set<String> getClassDescriptors() { |
| return Collections.singleton(descriptor); |
| } |
| |
| @Override |
| public Origin getOrigin() { |
| return origin; |
| } |
| } |
| |
| private static class ClassFileResourceProvider implements ProgramResourceProvider { |
| |
| private final List<ProgramResource> resources; |
| |
| public ClassFileResourceProvider(List<ProgramResource> resources) { |
| this.resources = resources; |
| } |
| |
| @Override |
| public Collection<ProgramResource> getProgramResources() throws ResourceException { |
| return resources; |
| } |
| |
| @Override |
| public DataResourceProvider getDataResourceProvider() { |
| return null; |
| } |
| } |
| |
| // Ordered list of classpath entries. |
| private List<Path> classpath = new ArrayList<>(); |
| |
| private AndroidApp.Builder builder = AndroidApp.builder(); |
| |
| private JvmTestBuilder(TestState state) { |
| super(state); |
| } |
| |
| public static JvmTestBuilder create(TestState state) { |
| return new JvmTestBuilder(state); |
| } |
| |
| @Override |
| JvmTestBuilder self() { |
| return this; |
| } |
| |
| @Override |
| public JvmTestRunResult run(String mainClass) throws IOException { |
| ProcessResult result = ToolHelper.runJava(classpath, mainClass); |
| return new JvmTestRunResult(builder.build(), result); |
| } |
| |
| @Override |
| public DebugTestConfig debugConfig() { |
| return new CfDebugTestConfig().addPaths(classpath); |
| } |
| |
| @Override |
| public JvmTestBuilder addLibraryFiles(Collection<Path> files) { |
| throw new Unimplemented("No support for changing the Java runtime library."); |
| } |
| |
| @Override |
| public JvmTestBuilder addProgramClasses(Collection<Class<?>> classes) { |
| addProgramResources(ListUtils.map(classes, ClassFileResource::new)); |
| return self(); |
| } |
| |
| @Override |
| public JvmTestBuilder addProgramFiles(Collection<Path> files) { |
| throw new Unimplemented( |
| "No support for adding paths directly (we need to compute the descriptor)"); |
| } |
| |
| @Override |
| public JvmTestBuilder addProgramClassFileData(Collection<byte[]> files) { |
| addProgramResources( |
| ListUtils.map(files, data -> |
| ProgramResource.fromBytes( |
| Origin.unknown(), |
| Kind.CF, |
| data, |
| Collections.singleton(TestBase.extractClassDescriptor(data))))); |
| return self(); |
| } |
| |
| public JvmTestBuilder addClasspath(Path... paths) { |
| return addClasspath(Arrays.asList(paths)); |
| } |
| |
| public JvmTestBuilder addClasspath(List<Path> paths) { |
| for (Path path : paths) { |
| assert Files.isDirectory(path) || FileUtils.isArchive(path); |
| classpath.add(path); |
| } |
| return self(); |
| } |
| |
| public JvmTestBuilder addTestClasspath() { |
| return addClasspath(ToolHelper.getClassPathForTests()); |
| } |
| |
| // Adding a collection of resources will build a jar of exactly those classes so that no other |
| // classes are made available via a too broad classpath directory. |
| private void addProgramResources(List<ProgramResource> resources) { |
| AndroidApp build = |
| AndroidApp.builder() |
| .addProgramResourceProvider(new ClassFileResourceProvider(resources)) |
| .build(); |
| Path out; |
| try { |
| out = getState().getNewTempFolder().resolve("out.zip"); |
| build.writeToZip(out, OutputMode.ClassFile); |
| } catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| classpath.add(out); |
| builder.addProgramFiles(out); |
| } |
| } |