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.invoker; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.fail; 20 import static org.mockito.Mockito.mock; 21 22 import com.android.tradefed.config.Configuration; 23 import com.android.tradefed.config.DeviceConfigurationHolder; 24 import com.android.tradefed.config.IConfiguration; 25 import com.android.tradefed.config.IDeviceConfiguration; 26 import com.android.tradefed.device.DeviceNotAvailableException; 27 import com.android.tradefed.device.ITestDevice; 28 import com.android.tradefed.device.metric.BaseDeviceMetricCollector; 29 import com.android.tradefed.device.metric.IMetricCollector; 30 import com.android.tradefed.device.metric.IMetricCollectorReceiver; 31 import com.android.tradefed.result.ITestInvocationListener; 32 import com.android.tradefed.targetprep.IHostCleaner; 33 import com.android.tradefed.targetprep.ITargetCleaner; 34 import com.android.tradefed.targetprep.ITargetPreparer; 35 import com.android.tradefed.targetprep.multi.IMultiTargetPreparer; 36 import com.android.tradefed.testtype.IRemoteTest; 37 import com.android.tradefed.util.IDisableable; 38 39 import org.easymock.EasyMock; 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.junit.runners.JUnit4; 44 import org.mockito.InOrder; 45 import org.mockito.Mockito; 46 47 import java.util.ArrayList; 48 import java.util.Arrays; 49 import java.util.List; 50 51 /** 52 * Unit tests for {@link InvocationExecution}. Tests for each individual interface of 53 * InvocationExecution, integration tests for orders or calls should be in {@link 54 * TestInvocationTest}. 55 */ 56 @RunWith(JUnit4.class) 57 public class InvocationExecutionTest { 58 private InvocationExecution mExec; 59 private IInvocationContext mContext; 60 private IConfiguration mConfig; 61 private ITestInvocationListener mMockListener; 62 63 @Before 64 public void setUp() { 65 mExec = new InvocationExecution(); 66 mContext = new InvocationContext(); 67 mConfig = new Configuration("test", "test"); 68 mMockListener = mock(ITestInvocationListener.class); 69 } 70 71 /** Test class for a target preparer class that also do host cleaner. */ 72 public interface ITargetHostCleaner extends ITargetPreparer, IHostCleaner {} 73 74 /** 75 * Test that {@link InvocationExecution#doCleanUp(IInvocationContext, IConfiguration, 76 * Throwable)} properly use {@link IDisableable} to let an object run. 77 */ 78 @Test 79 public void testCleanUp() throws Exception { 80 DeviceConfigurationHolder holder = new DeviceConfigurationHolder("default"); 81 ITargetHostCleaner cleaner = EasyMock.createMock(ITargetHostCleaner.class); 82 holder.addSpecificConfig(cleaner); 83 mConfig.setDeviceConfig(holder); 84 mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class)); 85 EasyMock.expect(cleaner.isDisabled()).andReturn(false); 86 EasyMock.expect(cleaner.isTearDownDisabled()).andReturn(false); 87 cleaner.cleanUp(null, null); 88 EasyMock.replay(cleaner); 89 mExec.doCleanUp(mContext, mConfig, null); 90 EasyMock.verify(cleaner); 91 } 92 93 /** 94 * Test that {@link InvocationExecution#doCleanUp(IInvocationContext, IConfiguration, 95 * Throwable)} properly use {@link IDisableable} to prevent an object from running. 96 */ 97 @Test 98 public void testCleanUp_disabled() throws Exception { 99 DeviceConfigurationHolder holder = new DeviceConfigurationHolder("default"); 100 ITargetHostCleaner cleaner = EasyMock.createMock(ITargetHostCleaner.class); 101 holder.addSpecificConfig(cleaner); 102 mConfig.setDeviceConfig(holder); 103 mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class)); 104 EasyMock.expect(cleaner.isDisabled()).andReturn(true); 105 // cleaner.isTearDownDisabled not expected, because isDisabled true stops || execution. 106 // cleanUp call is not expected 107 EasyMock.replay(cleaner); 108 mExec.doCleanUp(mContext, mConfig, null); 109 EasyMock.verify(cleaner); 110 } 111 112 /** 113 * Test that {@link InvocationExecution#doCleanUp(IInvocationContext, IConfiguration, 114 * Throwable)} properly use {@link IDisableable} isTearDownDisabled to prevent cleanup step. 115 */ 116 @Test 117 public void testCleanUp_tearDownDisabled() throws Exception { 118 DeviceConfigurationHolder holder = new DeviceConfigurationHolder("default"); 119 ITargetHostCleaner cleaner = EasyMock.createMock(ITargetHostCleaner.class); 120 holder.addSpecificConfig(cleaner); 121 mConfig.setDeviceConfig(holder); 122 mContext.addAllocatedDevice("default", EasyMock.createMock(ITestDevice.class)); 123 EasyMock.expect(cleaner.isDisabled()).andReturn(false); 124 EasyMock.expect(cleaner.isTearDownDisabled()).andReturn(true); 125 // cleanUp call is not expected 126 EasyMock.replay(cleaner); 127 mExec.doCleanUp(mContext, mConfig, null); 128 EasyMock.verify(cleaner); 129 } 130 131 /** 132 * Test {@link IRemoteTest} that also implements {@link IMetricCollectorReceiver} to test the 133 * init behavior. 134 */ 135 private static class RemoteTestCollector implements IRemoteTest, IMetricCollectorReceiver { 136 137 private List<IMetricCollector> mCollectors; 138 139 @Override 140 public void setMetricCollectors(List<IMetricCollector> collectors) { 141 mCollectors = collectors; 142 } 143 144 @Override 145 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 146 for (IMetricCollector collector : mCollectors) { 147 collector.init(new InvocationContext(), new ITestInvocationListener() {}); 148 } 149 } 150 } 151 152 public static class TestBaseMetricCollector extends BaseDeviceMetricCollector { 153 public static int sTotalInit = 0; 154 private boolean mFirstInit = true; 155 156 @Override 157 public ITestInvocationListener init( 158 IInvocationContext context, ITestInvocationListener listener) { 159 if (mFirstInit) { 160 sTotalInit++; 161 mFirstInit = false; 162 } else { 163 fail("Init should only be called once per instance."); 164 } 165 return super.init(context, listener); 166 } 167 } 168 169 /** 170 * Test that the collectors always run with the right context no matter where they are 171 * (re)initialized. 172 */ 173 @Test 174 public void testRun_metricCollectors() throws Exception { 175 List<IRemoteTest> tests = new ArrayList<>(); 176 // First add an IMetricCollectorReceiver 177 tests.add(new RemoteTestCollector()); 178 // Then a regular non IMetricCollectorReceiver 179 tests.add( 180 new IRemoteTest() { 181 @Override 182 public void run(ITestInvocationListener listener) 183 throws DeviceNotAvailableException {} 184 }); 185 mConfig.setTests(tests); 186 List<IMetricCollector> collectors = new ArrayList<>(); 187 collectors.add(new TestBaseMetricCollector()); 188 mConfig.setDeviceMetricCollectors(collectors); 189 mExec.runTests(mContext, mConfig, mMockListener); 190 // Init was called twice in total on the class, but only once per instance. 191 assertEquals(2, TestBaseMetricCollector.sTotalInit); 192 } 193 194 /** 195 * Test the ordering of multi_pre_target_preparer/target_preparer/multi_target_preparer during 196 * setup and tearDown. 197 */ 198 @Test 199 public void testDoSetup() throws Throwable { 200 IMultiTargetPreparer stub1 = mock(IMultiTargetPreparer.class); 201 IMultiTargetPreparer stub2 = mock(IMultiTargetPreparer.class); 202 IMultiTargetPreparer stub3 = mock(IMultiTargetPreparer.class); 203 IMultiTargetPreparer stub4 = mock(IMultiTargetPreparer.class); 204 mConfig.setMultiPreTargetPreparers(Arrays.asList(stub1, stub2)); 205 mConfig.setMultiTargetPreparers(Arrays.asList(stub3, stub4)); 206 207 ITargetCleaner cleaner = mock(ITargetCleaner.class); 208 IDeviceConfiguration holder = new DeviceConfigurationHolder("default"); 209 holder.addSpecificConfig(cleaner); 210 mConfig.setDeviceConfig(holder); 211 mContext.addAllocatedDevice("default", mock(ITestDevice.class)); 212 213 mExec.doSetup(mContext, mConfig, mMockListener); 214 mExec.doTeardown(mContext, mConfig, null); 215 216 // Pre multi preparers are always called before. 217 InOrder inOrder = Mockito.inOrder(stub1, stub2, stub3, stub4, cleaner); 218 inOrder.verify(stub1).isDisabled(); 219 inOrder.verify(stub1).setUp(mContext); 220 inOrder.verify(stub2).isDisabled(); 221 inOrder.verify(stub2).setUp(mContext); 222 223 inOrder.verify(cleaner).setUp(Mockito.any(), Mockito.any()); 224 225 inOrder.verify(stub3).isDisabled(); 226 inOrder.verify(stub3).setUp(mContext); 227 inOrder.verify(stub4).isDisabled(); 228 inOrder.verify(stub4).setUp(mContext); 229 230 // tear down 231 inOrder.verify(stub4).isDisabled(); 232 inOrder.verify(stub4).tearDown(mContext, null); 233 inOrder.verify(stub3).isDisabled(); 234 inOrder.verify(stub3).tearDown(mContext, null); 235 236 inOrder.verify(cleaner).tearDown(Mockito.any(), Mockito.any(), Mockito.any()); 237 238 inOrder.verify(stub2).isDisabled(); 239 inOrder.verify(stub2).tearDown(mContext, null); 240 inOrder.verify(stub1).isDisabled(); 241 inOrder.verify(stub1).tearDown(mContext, null); 242 } 243 } 244