19feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson/* 29feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * Copyright (C) 2013 The Android Open Source Project 39feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * 49feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * Licensed under the Apache License, Version 2.0 (the "License"); 59feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * you may not use this file except in compliance with the License. 69feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * You may obtain a copy of the License at 79feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * 89feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * http://www.apache.org/licenses/LICENSE-2.0 99feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * 109feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * Unless required by applicable law or agreed to in writing, software 119feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * distributed under the License is distributed on an "AS IS" BASIS, 129feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * See the License for the specific language governing permissions and 149feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson * limitations under the License. 159feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson */ 169feebf2627346eee3a9c6a117d7f279784a51720Orion Hodson 17f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarchepackage com.android.dx.merge; 18f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche 19f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarcheimport com.android.dex.Dex; 20f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarcheimport com.android.dex.DexIndexOverflowException; 219feebf2627346eee3a9c6a117d7f279784a51720Orion Hodsonimport com.android.dx.command.dexer.DxContext; 22f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche 23f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarcheimport java.io.File; 246b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodsonimport java.io.IOException; 256b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 266b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodsonimport java.util.concurrent.atomic.AtomicBoolean; 276b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodsonimport java.util.concurrent.Executors; 286b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodsonimport java.util.concurrent.ExecutorService; 296b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodsonimport java.util.concurrent.TimeUnit; 30259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canalimport java.util.Arrays; 31259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canalimport java.util.Random; 326b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodsonimport java.util.HashSet; 33f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche 34f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche/** 35259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal * This test tries to merge given dex files at random, a first pass at 2 by 2, followed by 36259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal * a second pass doing multi-way merges. 37f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche */ 38f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarchepublic class MergeTest { 39f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche 40f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche private static final int NUMBER_OF_TRIES = 1000; 41f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche 426b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson private static final int WORKER_THREADS = 4; 436b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 446b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson private static final ExecutorService executor = Executors.newFixedThreadPool(WORKER_THREADS); 456b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 466b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson // Helper task to concurrently run merge tests. 476b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson static class MergeTask implements Runnable { 486b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson private final DexMerger dexMerger; 496b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson private final String[] dexFiles; 506b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 516b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson MergeTask(String[] dexFiles, Dex[] dexesToMerge) throws IOException { 526b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson this.dexMerger = new DexMerger(dexesToMerge, CollisionPolicy.KEEP_FIRST, new DxContext()); 536b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson this.dexFiles = dexFiles; 546b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } 556b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 566b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson public void run() { 576b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson try { 586b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson dexMerger.merge(); 596b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } catch (DexIndexOverflowException e) { 606b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson // ignore index overflow 616b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } catch (Throwable t) { 626b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson System.err.println("Exception processing DEX files: " + t); 636b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson System.err.println("Problem merging those dexes: " + Arrays.toString(dexFiles)); 646b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson System.exit(1); 656b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } 666b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } 676b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } 686b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 69f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche public static void main(String[] args) throws Throwable { 70259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal Random random = new Random(); 716b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson HashSet<Integer> seen = new HashSet<>(); 72259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal for (int pass = 0; pass < 2; pass++) { 73259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal for (int i = 0; i < NUMBER_OF_TRIES; i++) { 74259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal // On the first pass only do 2-way merges, then do from 3 to 10 way merges 75259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal // but not more to avoid dex index overflow. 76259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal int numDex = pass == 0 ? 2 : random.nextInt(8) + 3; 7714c3baea81dbf0141551446d3f83ead8d4acd8f3Tobias Thierer numDex = Math.min(numDex, args.length); 786b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson String[] fileNames = new String[numDex]; 796b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson for (int j = 0; j < numDex; ++j) { 806b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson int fileIndex = random.nextInt(args.length); 816b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson fileNames[j] = args[fileIndex]; 826b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } 836b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 846b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson if (!seen.add(fileNames.hashCode())) { 856b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson // Skip, already seen set of file names with the same hash. 866b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson continue; 876b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } 886b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson 896b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson Dex[] dexesToMerge = new Dex[numDex]; 906b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson for (int j = 0; j < numDex; ++j) { 916b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson try { 926b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson dexesToMerge[j] = new Dex(new File(fileNames[j])); 936b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson } catch (IOException e) { 946b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson System.err.println("Error opening " + fileNames[j]); 956b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson System.err.println(e); 966b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson System.exit(1); 97259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal } 98259c2df556dd80998366fc23debb20cbd2d49be3Esteban de la Canal } 996b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson executor.execute(new MergeTask(fileNames, dexesToMerge)); 100f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche } 101f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche } 1026b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson executor.shutdown(); 1036b8ee006acd3ffb767808d5ca7762f90cca9bd48Orion Hodson executor.awaitTermination(8, TimeUnit.HOURS); 104f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche } 105f95ee7b39f09c13340387e5ae370b57589178b0fBenoit Lamarche} 106