blob: 8fdcfa58c6f66f075d225f2adc4e5ef073839ed9 [file] [log] [blame]
// Copyright (c) 2016, 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.internal;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.CompilationException;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.Resource;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.OutputMode;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
public class R8GMSCoreDeterministicTest extends GMSCoreCompilationTestBase {
public List<DexEncodedMethod> shuffle(List<DexEncodedMethod> methods) {
Collections.shuffle(methods);
return methods;
}
private AndroidApp doRun()
throws IOException, ProguardRuleParserException, CompilationException, ExecutionException {
R8Command command =
R8Command.builder().addProgramFiles(Paths.get(GMSCORE_V7_DIR, GMSCORE_APK)).build();
return ToolHelper.runR8(
command, options -> {
// For this test just do random shuffle.
options.testing.irOrdering = this::shuffle;
// Only use one thread to process to process in the order decided by the callback.
options.numberOfThreads = 1;
options.minApiLevel = Constants.ANDROID_L_API;
});
}
@Test
public void deterministic()
throws ExecutionException, IOException, ProguardRuleParserException, InterruptedException,
CompilationException {
// Run two independent compilations.
AndroidApp app1 = doRun();
AndroidApp app2 = doRun();
// Verify that the result of the two compilations was the same.
try (Closer closer = Closer.create()) {
List<Resource> files1 = app1.getDexProgramResources();
List<Resource> files2 = app2.getDexProgramResources();
assertEquals(files1.size(), files2.size());
for (int index = 0; index < files1.size(); index++) {
InputStream file1 = files1.get(index).getStream(closer);
InputStream file2 = files2.get(index).getStream(closer);
byte[] bytes1 = ByteStreams.toByteArray(file1);
byte[] bytes2 = ByteStreams.toByteArray(file2);
assertArrayEquals("File index " + index, bytes1, bytes2);
}
}
// Check that the generated bytecode runs through the dex2oat verifier with no errors.
Path combinedInput = temp.getRoot().toPath().resolve("all.jar");
Path oatFile = temp.getRoot().toPath().resolve("all.oat");
app1.writeToZip(combinedInput, OutputMode.Indexed);
ToolHelper.runDex2Oat(combinedInput, oatFile);
}
}