1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.compatibility.common.tradefed.presubmit; 17 18 import static org.junit.Assert.assertNotNull; 19 import static org.junit.Assert.assertTrue; 20 import static org.junit.Assert.fail; 21 22 import com.android.compatibility.common.tradefed.targetprep.FilePusher; 23 import com.android.tradefed.config.ConfigurationException; 24 import com.android.tradefed.config.ConfigurationFactory; 25 import com.android.tradefed.config.IConfiguration; 26 import com.android.tradefed.targetprep.ITargetPreparer; 27 import com.android.tradefed.targetprep.PushFilePreparer; 28 import com.android.tradefed.targetprep.TestAppInstallSetup; 29 import com.android.tradefed.testtype.IRemoteTest; 30 import com.android.tradefed.testtype.InstrumentationTest; 31 import com.android.tradefed.util.AaptParser; 32 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 import org.junit.runners.JUnit4; 36 37 import java.io.File; 38 import java.io.FilenameFilter; 39 import java.util.ArrayList; 40 import java.util.HashMap; 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.Set; 45 46 /** 47 * Class to validate tests Apks in testcases/ 48 */ 49 @RunWith(JUnit4.class) 50 public class ApkPackageNameCheck { 51 52 private static final Set<String> EXCEPTION_LIST = new HashSet<>(); 53 static { 54 // TODO: Remove exception when their package have been fixed. 55 EXCEPTION_LIST.add("android.app.cts"); 56 EXCEPTION_LIST.add("android.systemui.cts"); 57 } 58 59 /** 60 * We ensure that no apk with same package names may be installed. Otherwise it may results in 61 * conflicts. 62 */ 63 @Test testApkPackageNames()64 public void testApkPackageNames() throws Exception { 65 String ctsRoot = System.getProperty("CTS_ROOT"); 66 File testcases = new File(ctsRoot, "/android-cts/testcases/"); 67 if (!testcases.exists()) { 68 fail(String.format("%s does not exists", testcases)); 69 return; 70 } 71 File[] listConfig = testcases.listFiles(new FilenameFilter() { 72 @Override 73 public boolean accept(File dir, String name) { 74 if (name.endsWith(".config")) { 75 return true; 76 } 77 return false; 78 } 79 }); 80 assertTrue(listConfig.length > 0); 81 // We check all apk installed by all modules 82 Map<String, String> packageNames = new HashMap<>(); 83 84 for (File config : listConfig) { 85 IConfiguration c = ConfigurationFactory.getInstance() 86 .createConfigurationFromArgs(new String[] {config.getAbsolutePath()}); 87 // For each config, we check all the apk it's going to install 88 List<File> apkNames = new ArrayList<>(); 89 List<String> packageListNames = new ArrayList<>(); 90 for (ITargetPreparer prep : c.getTargetPreparers()) { 91 if (prep instanceof TestAppInstallSetup) { 92 apkNames.addAll(((TestAppInstallSetup) prep).getTestsFileName()); 93 } 94 // Ensure the files requested to be pushed exist. 95 if (prep instanceof FilePusher && ((FilePusher) prep).shouldAppendBitness()) { 96 for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) { 97 String path = f.getPath(); 98 if (!new File(testcases, path + "32").exists() 99 || !new File(testcases, path + "64").exists()) { 100 // TODO: Enforce should abort on failure is True in CTS 101 if (((FilePusher) prep).shouldAbortOnFailure()) { 102 fail( 103 String.format( 104 "File %s[32/64] wasn't found in testcases/ while " 105 + "it's expected to be pushed as part of " 106 + "%s", 107 path, config.getName())); 108 } 109 } 110 } 111 } else if (prep instanceof PushFilePreparer) { 112 for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) { 113 String path = f.getPath(); 114 if (!new File(testcases, path).exists()) { 115 // TODO: Enforce should abort on failure is True in CTS 116 if (((PushFilePreparer) prep).shouldAbortOnFailure()) { 117 fail( 118 String.format( 119 "File %s wasn't found in testcases/ while it's " 120 + "expected to be pushed as part of %s", 121 path, config.getName())); 122 } 123 } 124 } 125 } 126 } 127 128 for (File apk : apkNames) { 129 String apkName = apk.getName(); 130 File apkFile = new File(testcases, apkName); 131 if (!apkFile.exists()) { 132 fail(String.format("Module %s is trying to install %s which does not " 133 + "exists in testcases/", config.getName(), apkFile)); 134 } 135 AaptParser res = AaptParser.parse(apkFile); 136 assertNotNull(res); 137 String packageName = res.getPackageName(); 138 String put = packageNames.put(packageName, apkName); 139 packageListNames.add(packageName); 140 // The package already exists and it's a different apk 141 if (put != null && !apkName.equals(put) && !EXCEPTION_LIST.contains(packageName)) { 142 fail(String.format("Module %s: Package name '%s' from apk '%s' was already " 143 + "added by previous apk '%s'.", 144 config.getName(), packageName, apkName, put)); 145 } 146 } 147 148 // Catch a test trying to run something it doesn't install. 149 List<IRemoteTest> tests = c.getTests(); 150 for (IRemoteTest test : tests) { 151 if (test instanceof InstrumentationTest) { 152 InstrumentationTest instrumentationTest = (InstrumentationTest) test; 153 if (instrumentationTest.getPackageName() != null) { 154 if (!packageListNames.contains(instrumentationTest.getPackageName())) { 155 throw new ConfigurationException( 156 String.format("Module %s requests to run '%s' but it's not " 157 + "part of any apks.", 158 config.getName(), instrumentationTest.getPackageName())); 159 } 160 } 161 } 162 } 163 } 164 } 165 } 166