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.tradefed.sandbox; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertNotNull; 20 import static org.junit.Assert.assertNull; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 24 import com.android.tradefed.command.CommandOptions; 25 import com.android.tradefed.config.Configuration; 26 import com.android.tradefed.config.ConfigurationDescriptor; 27 import com.android.tradefed.config.ConfigurationException; 28 import com.android.tradefed.config.GlobalConfiguration; 29 import com.android.tradefed.config.IConfiguration; 30 import com.android.tradefed.config.OptionSetter; 31 import com.android.tradefed.invoker.IInvocationContext; 32 import com.android.tradefed.invoker.InvocationContext; 33 import com.android.tradefed.result.ITestInvocationListener; 34 import com.android.tradefed.result.LogDataType; 35 import com.android.tradefed.util.CommandResult; 36 import com.android.tradefed.util.CommandStatus; 37 import com.android.tradefed.util.FileUtil; 38 import com.android.tradefed.util.IRunUtil; 39 import com.android.tradefed.util.IRunUtil.EnvPriority; 40 41 import org.easymock.EasyMock; 42 import org.junit.After; 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.junit.runners.JUnit4; 47 48 import java.io.File; 49 50 /** Unit tests for {@link com.android.tradefed.sandbox.TradefedSandbox}. */ 51 @RunWith(JUnit4.class) 52 public class TradefedSandboxTest { 53 private static final String TF_JAR_DIR = "TF_JAR_DIR"; 54 private String mCachedProperty; 55 private File mTmpFolder; 56 57 private TradefedSandbox mSandbox; 58 private ITestInvocationListener mMockListener; 59 private IConfiguration mMockConfig; 60 private IInvocationContext mMockContext; 61 private IRunUtil mMockRunUtil; 62 63 @Before setUp()64 public void setUp() throws Exception { 65 mMockRunUtil = EasyMock.createMock(IRunUtil.class); 66 mSandbox = 67 new TradefedSandbox() { 68 @Override 69 IRunUtil createRunUtil() { 70 return mMockRunUtil; 71 } 72 }; 73 mMockListener = EasyMock.createMock(ITestInvocationListener.class); 74 mMockConfig = EasyMock.createMock(IConfiguration.class); 75 EasyMock.expect(mMockConfig.getConfigurationObject(Configuration.SANBOX_OPTIONS_TYPE_NAME)) 76 .andStubReturn(new SandboxOptions()); 77 mMockContext = new InvocationContext(); 78 mMockContext.setConfigurationDescriptor(new ConfigurationDescriptor()); 79 80 mTmpFolder = FileUtil.createTempDir("tmp-tf-jar-dir"); 81 82 if (System.getProperty(TF_JAR_DIR) != null) { 83 mCachedProperty = System.getProperty(TF_JAR_DIR); 84 } 85 System.setProperty(TF_JAR_DIR, mTmpFolder.getAbsolutePath()); 86 try { 87 GlobalConfiguration.createGlobalConfiguration(new String[] {}); 88 } catch (IllegalStateException ignore) { 89 // ignore the global config re-init 90 } 91 } 92 93 @After tearDown()94 public void tearDown() { 95 if (mCachedProperty != null) { 96 System.setProperty(TF_JAR_DIR, mCachedProperty); 97 } 98 FileUtil.recursiveDelete(mTmpFolder); 99 mSandbox.tearDown(); 100 } 101 102 /** 103 * Test a case where the {@link 104 * com.android.tradefed.sandbox.TradefedSandbox#prepareEnvironment(IInvocationContext, 105 * IConfiguration, ITestInvocationListener)} succeed and does not have any exception. 106 */ 107 @Test testPrepareEnvironment()108 public void testPrepareEnvironment() throws Exception { 109 mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE); 110 EasyMock.expectLastCall().times(2); 111 mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE); 112 EasyMock.expectLastCall().times(2); 113 mMockRunUtil.setEnvVariable( 114 EasyMock.eq(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE), EasyMock.anyObject()); 115 mMockRunUtil.setEnvVariablePriority(EnvPriority.SET); 116 mMockListener.testLog( 117 EasyMock.eq("sandbox-global-config"), 118 EasyMock.eq(LogDataType.XML), 119 EasyMock.anyObject()); 120 CommandResult result = new CommandResult(); 121 result.setStatus(CommandStatus.SUCCESS); 122 EasyMock.expect( 123 mMockRunUtil.runTimedCmd( 124 EasyMock.anyLong(), 125 EasyMock.eq("java"), 126 EasyMock.eq("-cp"), 127 EasyMock.anyObject(), 128 EasyMock.eq(SandboxConfigDump.class.getCanonicalName()), 129 EasyMock.eq("RUN_CONFIG"), 130 EasyMock.anyObject(), 131 EasyMock.eq("empty"), 132 EasyMock.eq("--arg"), 133 EasyMock.eq("1"), 134 EasyMock.eq("--use-proto-reporter"))) 135 .andReturn(result); 136 setPrepareConfigurationExpectations(); 137 EasyMock.replay(mMockConfig, mMockListener, mMockRunUtil); 138 Exception res = mSandbox.prepareEnvironment(mMockContext, mMockConfig, mMockListener); 139 EasyMock.verify(mMockConfig, mMockListener, mMockRunUtil); 140 assertNull(res); 141 } 142 143 /** 144 * Test a case where the {@link 145 * com.android.tradefed.sandbox.TradefedSandbox#prepareEnvironment(IInvocationContext, 146 * IConfiguration, ITestInvocationListener)} fails to dump the configuration, in that case the 147 * std err from the dump utility is used for the exception. 148 */ 149 @Test testPrepareEnvironment_dumpConfigFail()150 public void testPrepareEnvironment_dumpConfigFail() throws Exception { 151 mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE); 152 EasyMock.expectLastCall().times(2); 153 mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE); 154 EasyMock.expectLastCall().times(2); 155 mMockRunUtil.setEnvVariable( 156 EasyMock.eq(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE), EasyMock.anyObject()); 157 mMockRunUtil.setEnvVariablePriority(EnvPriority.SET); 158 mMockListener.testLog( 159 EasyMock.eq("sandbox-global-config"), 160 EasyMock.eq(LogDataType.XML), 161 EasyMock.anyObject()); 162 CommandResult result = new CommandResult(); 163 result.setStatus(CommandStatus.FAILED); 164 result.setStderr("Ouch I failed."); 165 EasyMock.expect( 166 mMockRunUtil.runTimedCmd( 167 EasyMock.anyLong(), 168 EasyMock.eq("java"), 169 EasyMock.eq("-cp"), 170 EasyMock.anyObject(), 171 EasyMock.eq(SandboxConfigDump.class.getCanonicalName()), 172 EasyMock.eq("RUN_CONFIG"), 173 EasyMock.anyObject(), 174 EasyMock.eq("empty"), 175 EasyMock.eq("--arg"), 176 EasyMock.eq("1"), 177 EasyMock.eq("--use-proto-reporter"))) 178 .andReturn(result); 179 setPrepareConfigurationExpectations(); 180 EasyMock.replay(mMockConfig, mMockListener, mMockRunUtil); 181 Exception res = mSandbox.prepareEnvironment(mMockContext, mMockConfig, mMockListener); 182 EasyMock.verify(mMockConfig, mMockListener, mMockRunUtil); 183 assertNotNull(res); 184 assertTrue(res instanceof ConfigurationException); 185 assertEquals("Error when dumping the config. stderr: Ouch I failed.", res.getMessage()); 186 } 187 188 /** 189 * Test a case where the {@link 190 * com.android.tradefed.sandbox.TradefedSandbox#prepareEnvironment(IInvocationContext, 191 * IConfiguration, ITestInvocationListener)} throws an exception because TF_JAR_DIR was not set. 192 */ 193 @Test testPrepareEnvironment_noTfDirJar()194 public void testPrepareEnvironment_noTfDirJar() throws Exception { 195 mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE); 196 mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_SERVER_CONFIG_VARIABLE); 197 EasyMock.expect(mMockConfig.getCommandLine()).andReturn("empty --arg 1"); 198 EasyMock.expect(mMockConfig.getCommandOptions()).andStubReturn(new CommandOptions()); 199 System.setProperty(TF_JAR_DIR, ""); 200 EasyMock.replay(mMockConfig, mMockListener, mMockRunUtil); 201 Exception res = mSandbox.prepareEnvironment(mMockContext, mMockConfig, mMockListener); 202 EasyMock.verify(mMockConfig, mMockListener, mMockRunUtil); 203 assertNotNull(res); 204 assertTrue(res instanceof ConfigurationException); 205 assertEquals( 206 "Could not read TF_JAR_DIR to get current Tradefed instance.", res.getMessage()); 207 } 208 setPrepareConfigurationExpectations()209 private void setPrepareConfigurationExpectations() throws Exception { 210 EasyMock.expect(mMockConfig.getCommandLine()).andReturn("empty --arg 1").times(2); 211 EasyMock.expect(mMockConfig.getCommandOptions()).andStubReturn(new CommandOptions()); 212 } 213 214 /** 215 * Test that when the sandbox option received a TF location, it uses it instead of the current 216 * one. 217 */ 218 @Test testSandboxOptions()219 public void testSandboxOptions() throws Exception { 220 File tmpDir = FileUtil.createTempDir("tmp-sandbox-dir"); 221 try { 222 mMockConfig = new Configuration("NAME", "DESC"); 223 mMockConfig.setCommandLine(new String[] {"empty", "--arg", "1"}); 224 SandboxOptions options = new SandboxOptions(); 225 OptionSetter setter = new OptionSetter(options); 226 setter.setOptionValue("sandbox:tf-location", tmpDir.getAbsolutePath()); 227 mMockConfig.setConfigurationObject(Configuration.SANBOX_OPTIONS_TYPE_NAME, options); 228 229 EasyMock.replay(mMockListener, mMockRunUtil); 230 File res = 231 mSandbox.getTradefedSandboxEnvironment( 232 mMockContext, mMockConfig, new String[] {"empty", "--arg", "1"}); 233 EasyMock.verify(mMockListener, mMockRunUtil); 234 assertEquals(tmpDir, res); 235 } finally { 236 FileUtil.recursiveDelete(tmpDir); 237 } 238 } 239 240 /** 241 * Test that when the sandbox option received a TF location and a build id at the same time that 242 * it is rejected, because that combination is not supported. 243 */ 244 @Test testSandboxOptions_exclusion()245 public void testSandboxOptions_exclusion() throws Exception { 246 File tmpDir = FileUtil.createTempDir("tmp-sandbox-dir"); 247 try { 248 mMockConfig = new Configuration("NAME", "DESC"); 249 mMockConfig.setCommandLine(new String[] {"empty", "--arg", "1"}); 250 SandboxOptions options = new SandboxOptions(); 251 OptionSetter setter = new OptionSetter(options); 252 setter.setOptionValue("sandbox:tf-location", tmpDir.getAbsolutePath()); 253 setter.setOptionValue("sandbox:sandbox-build-id", "9999"); 254 mMockConfig.setConfigurationObject(Configuration.SANBOX_OPTIONS_TYPE_NAME, options); 255 256 EasyMock.replay(mMockListener, mMockRunUtil); 257 try { 258 mSandbox.getTradefedSandboxEnvironment( 259 mMockContext, mMockConfig, new String[] {"empty", "--arg", "1"}); 260 fail("Should have thrown an exception."); 261 } catch (ConfigurationException expected) { 262 assertEquals( 263 "Sandbox options tf-location and sandbox-build-id cannot be set at " 264 + "the same time", 265 expected.getMessage()); 266 } 267 EasyMock.verify(mMockListener, mMockRunUtil); 268 } finally { 269 FileUtil.recursiveDelete(tmpDir); 270 } 271 } 272 } 273