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.targetprep; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 27 import com.android.tradefed.build.IBuildInfo; 28 import com.android.tradefed.build.VersionedFile; 29 import com.android.tradefed.config.ConfigurationDescriptor; 30 import com.android.tradefed.config.OptionSetter; 31 import com.android.tradefed.device.ITestDevice; 32 import com.android.tradefed.invoker.IInvocationContext; 33 import com.android.tradefed.invoker.InvocationContext; 34 import com.android.tradefed.invoker.TestInformation; 35 import com.android.tradefed.targetprep.TargetSetupError; 36 import com.android.tradefed.util.FileUtil; 37 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.junit.runners.JUnit4; 42 import org.mockito.ArgumentCaptor; 43 import org.mockito.Mockito; 44 45 import java.io.File; 46 import java.io.FileNotFoundException; 47 import java.util.ArrayList; 48 import java.util.Arrays; 49 import java.util.Collection; 50 import java.util.HashMap; 51 import java.util.Map; 52 53 /** 54 * Unit tests for {@link DynamicConfigPusher}. 55 */ 56 @RunWith(JUnit4.class) 57 public class DynamicConfigPusherTest { 58 private static final String RESOURCE_DYNAMIC_CONFIG = "test-dynamic-config"; 59 private static final String RUN_TESTS_AS_USER_KEY = "RUN_TESTS_AS_USER"; 60 private DynamicConfigPusher mPreparer; 61 private ITestDevice mMockDevice; 62 private CompatibilityBuildHelper mMockBuildHelper; 63 private IBuildInfo mMockBuildInfo; 64 private IInvocationContext mModuleContext; 65 private TestInformation mTestInfo; 66 67 @Before setUp()68 public void setUp() { 69 mModuleContext = new InvocationContext(); 70 mModuleContext.setConfigurationDescriptor(new ConfigurationDescriptor()); 71 mPreparer = new DynamicConfigPusher(); 72 mMockDevice = Mockito.mock(ITestDevice.class); 73 mMockBuildInfo = Mockito.mock(IBuildInfo.class); 74 mMockBuildHelper = new CompatibilityBuildHelper(mMockBuildInfo); 75 when(mMockDevice.getDeviceDescriptor()).thenReturn(null); 76 mModuleContext.addDeviceBuildInfo("device", mMockBuildInfo); 77 mModuleContext.addAllocatedDevice("device", mMockDevice); 78 mTestInfo = TestInformation.newBuilder().setInvocationContext(mModuleContext).build(); 79 } 80 81 /** 82 * Test getSuiteName from /test-suite-info.properties. 83 */ 84 @Test testGetSuiteName_fromTestSuiteInfo()85 public void testGetSuiteName_fromTestSuiteInfo() throws Exception { 86 mPreparer = new DynamicConfigPusher(); 87 mPreparer.setInvocationContext(mModuleContext); 88 89 assertNotNull(mPreparer.getSuiteName()); 90 } 91 92 /** 93 * Test getSuiteName from test-suite-tag. 94 */ 95 @Test testGetSuiteName_fromTestSuiteTag()96 public void testGetSuiteName_fromTestSuiteTag() throws Exception { 97 mPreparer = new DynamicConfigPusher(); 98 mModuleContext 99 .getConfigurationDescriptor() 100 .setSuiteTags(Arrays.asList("cts", "cts-instant", "gts")); 101 mPreparer.setInvocationContext(mModuleContext); 102 103 assertNotNull(mPreparer.getSuiteName()); 104 } 105 106 /** 107 * Test that when we look up resources locally, we search them from the build helper. 108 */ 109 @Test testLocalRead_fromDynamicConfigName()110 public void testLocalRead_fromDynamicConfigName() throws Exception { 111 OptionSetter setter = new OptionSetter(mPreparer); 112 setter.setOptionValue("config-filename", "config-test-name"); 113 setter.setOptionValue("dynamic-config-name", "dynamic-config-test-name"); 114 setter.setOptionValue("extract-from-resource", "false"); 115 116 File check = new File("anyfilewilldo"); 117 mMockBuildHelper = new CompatibilityBuildHelper(mMockBuildInfo) { 118 @Override 119 public File getTestFile(String filename) throws FileNotFoundException { 120 return check; 121 } 122 }; 123 124 File res = mPreparer.getLocalConfigFile(mMockBuildHelper, mMockDevice); 125 assertEquals(check, res); 126 } 127 128 /** 129 * Test that when we look up resources locally, we search them from the build helper. 130 */ 131 @Test testLocalRead()132 public void testLocalRead() throws Exception { 133 OptionSetter setter = new OptionSetter(mPreparer); 134 setter.setOptionValue("config-filename", "config-test-name"); 135 setter.setOptionValue("extract-from-resource", "false"); 136 137 File check = new File("anyfilewilldo"); 138 mMockBuildHelper = new CompatibilityBuildHelper(mMockBuildInfo) { 139 @Override 140 public File getTestFile(String filename) throws FileNotFoundException { 141 return check; 142 } 143 }; 144 145 File res = mPreparer.getLocalConfigFile(mMockBuildHelper, mMockDevice); 146 assertEquals(check, res); 147 } 148 149 /** 150 * Test that when we look up resources locally, we search them from the build helper and throw 151 * if it's not found. 152 */ 153 @Test testLocalRead_fileNotFound()154 public void testLocalRead_fileNotFound() throws Exception { 155 OptionSetter setter = new OptionSetter(mPreparer); 156 setter.setOptionValue("config-filename", "config-test-name"); 157 setter.setOptionValue("extract-from-resource", "false"); 158 159 mMockBuildHelper = new CompatibilityBuildHelper(mMockBuildInfo) { 160 @Override 161 public File getTestFile(String filename) throws FileNotFoundException { 162 throw new FileNotFoundException("test"); 163 } 164 }; 165 try { 166 mPreparer.getLocalConfigFile(mMockBuildHelper, mMockDevice); 167 fail("Should have thrown an exception."); 168 } catch (TargetSetupError expected) { 169 // expected 170 assertEquals( 171 "Cannot get local dynamic config file from test directory", 172 expected.getMessage()); 173 } 174 } 175 176 /** 177 * Test when we try to unpack a resource but it does not exists. 178 */ 179 @Test testResourceRead_notFound()180 public void testResourceRead_notFound() throws Exception { 181 OptionSetter setter = new OptionSetter(mPreparer); 182 setter.setOptionValue("config-filename", "not-an-existing-resource-name"); 183 setter.setOptionValue("extract-from-resource", "true"); 184 try { 185 mPreparer.getLocalConfigFile(mMockBuildHelper, mMockDevice); 186 fail("Should have thrown an exception."); 187 } catch (TargetSetupError expected) { 188 // expected 189 assertEquals( 190 "Fail to unpack 'not-an-existing-resource-name.dynamic' from resources", 191 expected.getMessage()); 192 } 193 } 194 195 /** 196 * Test when we get a config from the resources. 197 */ 198 @Test testResourceRead()199 public void testResourceRead() throws Exception { 200 OptionSetter setter = new OptionSetter(mPreparer); 201 setter.setOptionValue("config-filename", RESOURCE_DYNAMIC_CONFIG); 202 setter.setOptionValue("extract-from-resource", "true"); 203 File res = null; 204 try { 205 res = mPreparer.getLocalConfigFile(mMockBuildHelper, mMockDevice); 206 assertTrue(res.exists()); 207 assertTrue(FileUtil.readStringFromFile(res).contains("<dynamicConfig>")); 208 } finally { 209 FileUtil.deleteFile(res); 210 } 211 } 212 213 /** 214 * Test when we get a config from the resources under the alternative name. 215 */ 216 @Test testResourceRead_resourceFileName()217 public void testResourceRead_resourceFileName() throws Exception { 218 OptionSetter setter = new OptionSetter(mPreparer); 219 setter.setOptionValue("config-filename", "moduleName"); 220 setter.setOptionValue("extract-from-resource", "true"); 221 // Look up the file under that name instead of the config-filename 222 setter.setOptionValue("dynamic-resource-name", RESOURCE_DYNAMIC_CONFIG); 223 File res = null; 224 try { 225 res = mPreparer.getLocalConfigFile(mMockBuildHelper, mMockDevice); 226 assertTrue(res.exists()); 227 assertTrue(FileUtil.readStringFromFile(res).contains("<dynamicConfig>")); 228 } finally { 229 FileUtil.deleteFile(res); 230 } 231 } 232 233 @Test testSetUp_usesRunTestsAsUserFromProperty()234 public void testSetUp_usesRunTestsAsUserFromProperty() throws Exception { 235 final File[] localConfig = new File[1]; 236 OptionSetter setter = prepareSetupTestTarget(localConfig); 237 // Set target to DEVICE. 238 setter.setOptionValue("target", "device"); 239 240 int runTestsAsUserId = 101; 241 mTestInfo.properties().put(RUN_TESTS_AS_USER_KEY, String.valueOf(runTestsAsUserId)); 242 when(mMockDevice.pushFile(Mockito.any(), Mockito.any(), Mockito.anyInt())).thenReturn(true); 243 244 mPreparer.setUp(mTestInfo); 245 246 verify(mMockDevice, Mockito.never()).getCurrentUser(); 247 // pushFile() is called for the RUN_TESTS_AS_USER set in the TestInfo property. 248 verify(mMockDevice).pushFile(Mockito.any(), Mockito.any(), Mockito.eq(runTestsAsUserId)); 249 } 250 251 @Test testSetUp_currentUser()252 public void testSetUp_currentUser() throws Exception { 253 final File[] localConfig = new File[1]; 254 OptionSetter setter = prepareSetupTestTarget(localConfig); 255 // Set target to DEVICE. 256 setter.setOptionValue("target", "device"); 257 258 int currentUserId = 100; 259 when(mMockDevice.getCurrentUser()).thenReturn(currentUserId); 260 when(mMockDevice.pushFile(Mockito.any(), Mockito.any(), Mockito.anyInt())).thenReturn(true); 261 262 mPreparer.setUp(mTestInfo); 263 264 // pushFile() is called for the current user. 265 verify(mMockDevice).pushFile(Mockito.any(), Mockito.any(), Mockito.eq(currentUserId)); 266 } 267 268 /** 269 * Test an end-to-end usage of the dynamic config file from the jar. 270 */ 271 @Test testSetUp()272 public void testSetUp() throws Exception { 273 final File[] localConfig = new File[1]; 274 prepareSetupTestTarget(localConfig); 275 276 Map<String, String> attributes = new HashMap<>(); 277 attributes.put(CompatibilityBuildHelper.SUITE_VERSION, "v1"); 278 when(mMockBuildInfo.getBuildAttributes()).thenReturn(attributes); 279 Collection<VersionedFile> versionedFiles = new ArrayList<VersionedFile>(); 280 when(mMockBuildInfo.getFiles()).thenReturn(versionedFiles); 281 mPreparer.setInvocationContext(mModuleContext); 282 283 mPreparer.setUp(mTestInfo); 284 ArgumentCaptor<File> capture = ArgumentCaptor.forClass(File.class); 285 verify(mMockBuildInfo) 286 .setFile( 287 Mockito.contains("moduleName"), 288 capture.capture(), 289 Mockito.eq("DYNAMIC_CONFIG_FILE:moduleName")); 290 assertNotNull(localConfig[0]); 291 // Ensure that the extracted file was deleted. 292 assertFalse(localConfig[0].exists()); 293 File dynamicFile = capture.getValue(); 294 assertTrue(dynamicFile.exists()); 295 FileUtil.deleteFile(dynamicFile); 296 } 297 298 /** 299 * Prepares for running tests for DynamicConfigPusher#setUp method. 300 * 301 * @return an {@link OptionSetter} so that each test can override option valuses as necessary. 302 */ prepareSetupTestTarget(File[] localConfig)303 private OptionSetter prepareSetupTestTarget(File[] localConfig) throws Exception { 304 mPreparer = 305 new DynamicConfigPusher() { 306 @Override 307 File mergeConfigFiles( 308 File localConfigFile, 309 String apfeConfigInJson, 310 String moduleName, 311 ITestDevice device) 312 throws TargetSetupError { 313 localConfig[0] = localConfigFile; 314 return super.mergeConfigFiles( 315 localConfigFile, apfeConfigInJson, moduleName, device); 316 } 317 }; 318 OptionSetter setter = new OptionSetter(mPreparer); 319 setter.setOptionValue("has-server-side-config", "false"); 320 setter.setOptionValue("config-filename", "moduleName"); 321 setter.setOptionValue("extract-from-resource", "true"); 322 // Look up the file under that name instead of the config-filename 323 setter.setOptionValue("dynamic-resource-name", RESOURCE_DYNAMIC_CONFIG); 324 325 return setter; 326 } 327 } 328