1 /* 2 * Copyright (C) 2016 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.testtype; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertTrue; 20 import static org.junit.Assert.fail; 21 22 import com.android.tradefed.build.DeviceBuildInfo; 23 import com.android.tradefed.config.OptionSetter; 24 import com.android.tradefed.log.LogUtil.CLog; 25 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; 26 import com.android.tradefed.result.ITestInvocationListener; 27 import com.android.tradefed.result.TestDescription; 28 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics; 29 import com.android.tradefed.testtype.HostTest; 30 import com.android.tradefed.testtype.IRemoteTest; 31 import com.android.tradefed.util.FileUtil; 32 import com.android.tradefed.util.proto.TfMetricProtoUtil; 33 34 import org.easymock.EasyMock; 35 import org.junit.After; 36 import org.junit.Before; 37 import org.junit.Rule; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.junit.runners.JUnit4; 41 42 import java.io.File; 43 import java.io.IOException; 44 import java.io.InputStream; 45 import java.net.MalformedURLException; 46 import java.net.URL; 47 import java.net.URLClassLoader; 48 import java.util.Arrays; 49 import java.util.HashMap; 50 import java.util.List; 51 import java.util.Map; 52 53 /** 54 * Unit tests for {@link JarHostTest}. 55 */ 56 @RunWith(JUnit4.class) 57 public class JarHostTestTest { 58 59 private static final String TEST_JAR1 = "/testtype/testJar1.jar"; 60 private JarHostTest mTest; 61 private DeviceBuildInfo mStubBuildInfo; 62 private File mTestDir = null; 63 private ITestInvocationListener mListener; 64 65 /** 66 * More testable version of {@link JarHostTest} 67 */ 68 public static class JarHostTestable extends JarHostTest { 69 70 public static File mTestDir; JarHostTestable()71 public JarHostTestable() {} 72 JarHostTestable(File testDir)73 public JarHostTestable(File testDir) { 74 mTestDir = testDir; 75 } 76 } 77 78 @Before setUp()79 public void setUp() throws Exception { 80 mTest = new JarHostTest(); 81 mTestDir = FileUtil.createTempDir("jarhostest"); 82 mListener = EasyMock.createMock(ITestInvocationListener.class); 83 OptionSetter setter = new OptionSetter(mTest); 84 setter.setOptionValue("enable-pretty-logs", "false"); 85 mStubBuildInfo = new DeviceBuildInfo(); 86 mStubBuildInfo.setTestsDir(mTestDir, "v1"); 87 } 88 89 @After tearDown()90 public void tearDown() throws Exception { 91 FileUtil.recursiveDelete(mTestDir); 92 } 93 94 /** 95 * Helper to read a file from the res/testtype directory and return it. 96 * 97 * @param filename the name of the file in the res/testtype directory 98 * @param parentDir dir where to put the jar. Null if in default tmp directory. 99 * @return the extracted jar file. 100 */ getJarResource(String filename, File parentDir)101 protected File getJarResource(String filename, File parentDir) throws IOException { 102 InputStream jarFileStream = getClass().getResourceAsStream(filename); 103 File jarFile = FileUtil.createTempFile("test", ".jar", parentDir); 104 FileUtil.writeToFile(jarFileStream, jarFile); 105 return jarFile; 106 } 107 108 /** 109 * Test class, we have to annotate with full org.junit.Test to avoid name collision in import. 110 */ 111 @RunWith(JUnit4.class) 112 public static class Junit4TestClass { Junit4TestClass()113 public Junit4TestClass() {} 114 @org.junit.Test testPass1()115 public void testPass1() {} 116 } 117 118 /** 119 * Test class, we have to annotate with full org.junit.Test to avoid name collision in import. 120 */ 121 @RunWith(JUnit4.class) 122 public static class Junit4TestClass2 { Junit4TestClass2()123 public Junit4TestClass2() {} 124 @Rule public TestMetrics metrics = new TestMetrics(); 125 126 @org.junit.Test testPass2()127 public void testPass2() { 128 metrics.addTestMetric("key", "value"); 129 } 130 } 131 132 /** 133 * Test that {@link JarHostTest#split()} inherited from {@link HostTest} is still good. 134 */ 135 @Test testSplit_withoutJar()136 public void testSplit_withoutJar() throws Exception { 137 OptionSetter setter = new OptionSetter(mTest); 138 setter.setOptionValue("class", "com.android.compatibility.common.tradefed.testtype." 139 + "JarHostTestTest$Junit4TestClass"); 140 setter.setOptionValue("class", "com.android.compatibility.common.tradefed.testtype." 141 + "JarHostTestTest$Junit4TestClass2"); 142 // sharCount is ignored; will split by number of classes 143 List<IRemoteTest> res = (List<IRemoteTest>)mTest.split(1); 144 assertEquals(2, res.size()); 145 assertTrue(res.get(0) instanceof JarHostTest); 146 assertTrue(res.get(1) instanceof JarHostTest); 147 } 148 149 /** 150 * Test that {@link JarHostTest#split()} can split classes coming from a jar. 151 */ 152 @Test testSplit_withJar()153 public void testSplit_withJar() throws Exception { 154 File testJar = getJarResource(TEST_JAR1, mTestDir); 155 mTest = new JarHostTestable(mTestDir); 156 mTest.setBuild(mStubBuildInfo); 157 OptionSetter setter = new OptionSetter(mTest); 158 setter.setOptionValue("enable-pretty-logs", "false"); 159 setter.setOptionValue("jar", testJar.getName()); 160 // sharCount is ignored; will split by number of classes 161 List<IRemoteTest> res = (List<IRemoteTest>)mTest.split(1); 162 assertEquals(2, res.size()); 163 assertTrue(res.get(0) instanceof JarHostTest); 164 assertEquals("[android.ui.cts.TaskSwitchingTest]", 165 ((JarHostTest)res.get(0)).getClassNames().toString()); 166 assertTrue(res.get(1) instanceof JarHostTest); 167 assertEquals("[android.ui.cts.InstallTimeTest]", 168 ((JarHostTest)res.get(1)).getClassNames().toString()); 169 } 170 171 /** 172 * Testable version of {@link JarHostTest} that allows adding jar to classpath for testing 173 * purpose. 174 */ 175 public static class JarHostTestLoader extends JarHostTestable { 176 177 private static File mTestJar; 178 JarHostTestLoader()179 public JarHostTestLoader() {} 180 JarHostTestLoader(File testDir, File jar)181 public JarHostTestLoader(File testDir, File jar) { 182 super(testDir); 183 mTestJar = jar; 184 } 185 186 @Override getClassLoader()187 protected ClassLoader getClassLoader() { 188 ClassLoader child = super.getClassLoader(); 189 try { 190 child = new URLClassLoader(Arrays.asList(mTestJar.toURI().toURL()) 191 .toArray(new URL[]{}), super.getClassLoader()); 192 } catch (MalformedURLException e) { 193 CLog.e(e); 194 } 195 return child; 196 } 197 } 198 199 /** 200 * If a jar file is not found, the countTest will fail but we still want to report a 201 * testRunStart and End pair for results. 202 */ 203 @Test testCountTestFails()204 public void testCountTestFails() throws Exception { 205 OptionSetter setter = new OptionSetter(mTest); 206 setter.setOptionValue("jar", "thisjardoesnotexistatall.jar"); 207 mListener.testRunStarted(EasyMock.anyObject(), EasyMock.eq(0)); 208 mListener.testRunEnded(EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject()); 209 EasyMock.replay(mListener); 210 try { 211 mTest.run(mListener); 212 fail("Should have thrown an exception."); 213 } catch(RuntimeException expected) { 214 // expected 215 } 216 EasyMock.verify(mListener); 217 } 218 219 /** 220 * Test that metrics from tests in JarHost are reported and accounted for. 221 */ 222 @Test testJarHostMetrics()223 public void testJarHostMetrics() throws Exception { 224 OptionSetter setter = new OptionSetter(mTest); 225 setter.setOptionValue("class", "com.android.compatibility.common.tradefed.testtype." 226 + "JarHostTestTest$Junit4TestClass2"); 227 mListener.testRunStarted(EasyMock.anyObject(), EasyMock.eq(1)); 228 TestDescription tid = new TestDescription("com.android.compatibility.common.tradefed." 229 + "testtype.JarHostTestTest$Junit4TestClass2", "testPass2"); 230 mListener.testStarted(EasyMock.eq(tid), EasyMock.anyLong()); 231 Map<String, String> metrics = new HashMap<>(); 232 metrics.put("key", "value"); 233 mListener.testEnded(EasyMock.eq(tid), EasyMock.anyLong(), 234 EasyMock.eq(TfMetricProtoUtil.upgradeConvert(metrics))); 235 mListener.testRunEnded(EasyMock.anyLong(), (HashMap<String, Metric>) EasyMock.anyObject()); 236 EasyMock.replay(mListener); 237 mTest.run(mListener); 238 EasyMock.verify(mListener); 239 } 240 } 241