summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Gavrilovic <gavra@google.com>2017-03-22 17:47:16 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-03-22 17:47:16 +0000
commite4ecc9ff1d3ce159645db761747a5c1dda54ad24 (patch)
treefad6892fc54a1e03fc896f8d67503e8ac41cc377
parentf9dd52a4ebed02d3a4dace355ba7c34b7664ef47 (diff)
parenteebf335a7f3bcf53a3f2cf9437eaabdf40c3aefe (diff)
downloaddalvik-e4ecc9ff1d3ce159645db761747a5c1dda54ad24.tar.gz
Merge "Dex merger handles empty sections"
am: eebf335a7f Change-Id: I29915084793481443cec1c7fd5eeeee3223f7762
-rw-r--r--dx/junit-tests/com/android/dx/merge/DexMergerTest.java93
-rw-r--r--dx/src/com/android/dx/merge/DexMerger.java13
2 files changed, 106 insertions, 0 deletions
diff --git a/dx/junit-tests/com/android/dx/merge/DexMergerTest.java b/dx/junit-tests/com/android/dx/merge/DexMergerTest.java
new file mode 100644
index 000000000..b9f03929b
--- /dev/null
+++ b/dx/junit-tests/com/android/dx/merge/DexMergerTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dx.merge;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import com.android.dex.Dex;
+import com.android.dx.command.Main;
+import com.android.dx.command.dexer.DxContext;
+import java.io.ByteArrayOutputStream;
+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.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class DexMergerTest {
+ static class NoFieldsClassA {
+ }
+ static class NoFieldsClassB {
+ }
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Test
+ public void test_merge_dexesWithEmptyFieldsSection() throws IOException {
+ List<Dex> outputDexes = new ArrayList<>();
+ outputDexes.add(getDexForClass(NoFieldsClassA.class));
+ outputDexes.add(getDexForClass(NoFieldsClassB.class));
+
+ Dex merged =
+ new DexMerger(
+ outputDexes.toArray(new Dex[outputDexes.size()]),
+ CollisionPolicy.FAIL,
+ new DxContext())
+ .merge();
+ assertNotNull(merged);
+ assertNotNull(merged.getTableOfContents());
+ assertEquals(0, merged.getTableOfContents().fieldIds.off);
+ }
+
+ private Dex getDexForClass(Class<?> clazz) throws IOException {
+ String path = clazz.getName().replace('.', '/') + ".class";
+ Path classesJar = temporaryFolder.newFile(clazz.getName() + ".jar").toPath();
+ try (InputStream in = getClass().getClassLoader().getResourceAsStream(path);
+ ZipOutputStream zip = new ZipOutputStream(Files.newOutputStream(classesJar))) {
+
+ ZipEntry entry = new ZipEntry(path);
+ zip.putNextEntry(entry);
+ zip.write(readEntireStream(in));
+ zip.closeEntry();
+ }
+
+ Path output = temporaryFolder.newFolder().toPath();
+ Main.main(new String[]{"--dex", "--output=" + output.toString(), classesJar.toString()});
+
+ return new Dex(Files.readAllBytes(output.resolve("classes.dex")));
+ }
+
+ private static byte[] readEntireStream(InputStream inputStream) throws IOException {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ byte[] buffer = new byte[8192];
+
+ int count;
+ while ((count = inputStream.read(buffer)) != -1) {
+ bytesOut.write(buffer, 0, count);
+ }
+
+ return bytesOut.toByteArray();
+ }
+}
diff --git a/dx/src/com/android/dx/merge/DexMerger.java b/dx/src/com/android/dx/merge/DexMerger.java
index 470d8fb22..81ad2ddb7 100644
--- a/dx/src/com/android/dx/merge/DexMerger.java
+++ b/dx/src/com/android/dx/merge/DexMerger.java
@@ -166,6 +166,9 @@ public final class DexMerger {
unionAnnotationSetsAndDirectories();
mergeClassDefs();
+ // computeSizesFromOffsets expects sections sorted by offset, so make it so
+ Arrays.sort(contentsOut.sections);
+
// write the header
contentsOut.header.off = 0;
contentsOut.header.size = 1;
@@ -255,6 +258,11 @@ public final class DexMerger {
offsets[i] = readIntoMap(
dexSections[i], sections[i], indexMaps[i], indexes[i], values, i);
}
+ if (values.isEmpty()) {
+ getSection(contentsOut).off = 0;
+ getSection(contentsOut).size = 0;
+ return;
+ }
getSection(contentsOut).off = out.getPosition();
int outCount = 0;
@@ -299,6 +307,11 @@ public final class DexMerger {
for (int i = 0; i < dexes.length; i++) {
all.addAll(readUnsortedValues(dexes[i], indexMaps[i]));
}
+ if (all.isEmpty()) {
+ getSection(contentsOut).off = 0;
+ getSection(contentsOut).size = 0;
+ return;
+ }
Collections.sort(all);
int outCount = 0;