1 /* 2 * Copyright (C) 2022 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 17 package com.android.modules.targetprep; 18 19 import static com.android.modules.targetprep.ClasspathFetcher.DEVICE_JAR_ARTIFACTS_TAG; 20 import static com.google.common.truth.Truth.assertThat; 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertThrows; 23 import static org.junit.Assert.fail; 24 import static org.junit.Assume.assumeTrue; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Mockito.mock; 28 import static org.mockito.Mockito.times; 29 import static org.mockito.Mockito.verify; 30 import static org.mockito.Mockito.when; 31 32 33 import com.android.modules.proto.ClasspathClasses.ClasspathClassesDump; 34 import com.android.modules.proto.ClasspathClasses.ClasspathEntry; 35 import com.android.tradefed.build.IDeviceBuildInfo; 36 import com.android.tradefed.device.ITestDevice; 37 import com.android.tradefed.invoker.IInvocationContext; 38 import com.android.tradefed.invoker.InvocationContext; 39 import com.android.tradefed.invoker.TestInformation; 40 import com.android.tradefed.util.CommandResult; 41 import com.android.tradefed.util.CommandStatus; 42 43 import java.io.File; 44 import java.io.FileInputStream; 45 import java.io.InputStream; 46 import java.nio.file.Files; 47 import java.nio.file.StandardCopyOption; 48 import java.util.List; 49 50 import org.junit.Assert; 51 import org.junit.Before; 52 import org.junit.Rule; 53 import org.junit.Test; 54 import org.junit.rules.RuleChain; 55 import org.junit.rules.TemporaryFolder; 56 import org.junit.runner.RunWith; 57 import org.junit.runners.JUnit4; 58 59 import org.mockito.Mock; 60 import org.mockito.Mockito; 61 import org.mockito.MockitoAnnotations; 62 import org.mockito.stubbing.Answer; 63 64 @RunWith(JUnit4.class) 65 public class ClasspathFetcherTest { 66 67 private static final String SERIAL = "SERIAL"; 68 69 @Mock IDeviceBuildInfo mMockBuildInfo; 70 @Mock ITestDevice mMockTestDevice; 71 72 private TestInformation mTestInfo; 73 74 private String mBootclasspathJarNames = ""; 75 private String mSystemServerclasspathJarNames = ""; 76 77 @Before setUp()78 public void setUp() throws Exception { 79 MockitoAnnotations.initMocks(this); 80 81 when(mMockTestDevice.getSerialNumber()).thenReturn(SERIAL); 82 when(mMockTestDevice.getDeviceDescriptor()).thenReturn(null); 83 when(mMockTestDevice.isAppEnumerationSupported()).thenReturn(false); 84 when(mMockTestDevice.executeShellV2Command(eq("echo $BOOTCLASSPATH"))).then( 85 invocation -> { 86 return successfulCommandResult(mBootclasspathJarNames, ""); 87 } 88 ); 89 when(mMockTestDevice.executeShellV2Command(eq("echo $SYSTEMSERVERCLASSPATH"))).then( 90 invocation -> { 91 return successfulCommandResult(mSystemServerclasspathJarNames, ""); 92 } 93 ); 94 when(mMockTestDevice.pullFile(anyString())).then( 95 invocation -> { 96 final String path = invocation.getArgument(0); 97 final File tempFile = File.createTempFile(path, null); 98 99 try (InputStream is = 100 ClasspathFetcherTest.class.getClassLoader().getResourceAsStream(path)) { 101 Files.copy(is, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); 102 } 103 return tempFile; 104 } 105 ); 106 IInvocationContext context = new InvocationContext(); 107 context.addAllocatedDevice("device", mMockTestDevice); 108 context.addDeviceBuildInfo("device", mMockBuildInfo); 109 mTestInfo = TestInformation.newBuilder().setInvocationContext(context).build(); 110 } 111 112 @Test testSingleArtifactFetcher()113 public void testSingleArtifactFetcher() throws Exception { 114 mBootclasspathJarNames = "LibraryA.jar"; 115 mSystemServerclasspathJarNames = "LibraryB.jar"; 116 final ClasspathFetcher fetcher = new ClasspathFetcher(); 117 fetcher.setUp(mTestInfo); 118 assertThat(mTestInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)).isTrue(); 119 fetcher.tearDown(mTestInfo, null); 120 assertThat(mTestInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)).isFalse(); 121 } 122 123 @Test testMultipleArtifactFetchers()124 public void testMultipleArtifactFetchers() throws Exception { 125 mBootclasspathJarNames = "LibraryA.jar"; 126 mSystemServerclasspathJarNames = "LibraryB.jar"; 127 final ClasspathFetcher fetcher1 = new ClasspathFetcher(); 128 final ClasspathFetcher fetcher2 = new ClasspathFetcher(); 129 130 fetcher1.setUp(mTestInfo); 131 fetcher2.setUp(mTestInfo); 132 assertThat(mTestInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)).isTrue(); 133 fetcher2.tearDown(mTestInfo, null); 134 assertThat(mTestInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)).isTrue(); 135 fetcher1.tearDown(mTestInfo, null); 136 assertThat(mTestInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)).isFalse(); 137 } 138 139 @Test testFetchCorrectBcpClasses()140 public void testFetchCorrectBcpClasses() throws Exception { 141 mBootclasspathJarNames = "LibraryA.jar"; 142 mSystemServerclasspathJarNames = "LibraryB.jar"; 143 final ClasspathFetcher fetcher = new ClasspathFetcher(); 144 145 try { 146 fetcher.setUp(mTestInfo); 147 148 final File bcpProto = new File(mTestInfo.properties().get(DEVICE_JAR_ARTIFACTS_TAG), 149 ClasspathFetcher.BCP_CLASSES_FILE); 150 assertThat(bcpProto.exists()).isTrue(); 151 ClasspathClassesDump dump = 152 ClasspathClassesDump.parseFrom(new FileInputStream(bcpProto)); 153 List<ClasspathEntry> entries = dump.getEntriesList(); 154 assertThat(entries.size()).isEqualTo(1); 155 ClasspathEntry entry = entries.get(0); 156 assertThat(entry.hasJar()).isTrue(); 157 assertThat(entry.getJar().getPath()).isEqualTo("LibraryA.jar"); 158 assertThat(entry.getClassesList().size()).isEqualTo(1); 159 assertThat(entry.getClassesList().get(0)) 160 .isEqualTo("Lcom/android/modules/targetprep/android/A;"); 161 } finally { 162 fetcher.tearDown(mTestInfo, null); 163 } 164 } 165 166 @Test testFetchCorrectSscpClasses()167 public void testFetchCorrectSscpClasses() throws Exception { 168 mBootclasspathJarNames = "LibraryA.jar"; 169 mSystemServerclasspathJarNames = "LibraryB.jar"; 170 final ClasspathFetcher fetcher = new ClasspathFetcher(); 171 172 try { 173 fetcher.setUp(mTestInfo); 174 175 final File sscpProto = new File(mTestInfo.properties().get(DEVICE_JAR_ARTIFACTS_TAG), 176 ClasspathFetcher.SSCP_CLASSES_FILE); 177 assertThat(sscpProto.exists()).isTrue(); 178 ClasspathClassesDump dump = 179 ClasspathClassesDump.parseFrom(new FileInputStream(sscpProto)); 180 List<ClasspathEntry> entries = dump.getEntriesList(); 181 assertThat(entries.size()).isEqualTo(1); 182 ClasspathEntry entry = entries.get(0); 183 assertThat(entry.hasJar()).isTrue(); 184 assertThat(entry.getJar().getPath()).isEqualTo("LibraryB.jar"); 185 assertThat(entry.getClassesList().size()).isEqualTo(1); 186 assertThat(entry.getClassesList().get(0)) 187 .isEqualTo("Lcom/android/modules/targetprep/android/B;"); 188 } finally { 189 fetcher.tearDown(mTestInfo, null); 190 } 191 } 192 successfulCommandResult(String stdout, String stderr)193 private static CommandResult successfulCommandResult(String stdout, String stderr) { 194 final CommandResult result = new CommandResult(); 195 result.setStatus(CommandStatus.SUCCESS); 196 result.setExitCode(0); 197 result.setStdout(stdout); 198 result.setStderr(stderr); 199 return result; 200 } 201 202 } 203