1 /* 2 * Copyright (C) 2011 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.command.remote; 17 18 import com.android.tradefed.build.BuildInfo; 19 import com.android.tradefed.command.ICommandScheduler; 20 import com.android.tradefed.command.ICommandScheduler.IScheduledInvocationListener; 21 import com.android.tradefed.device.DeviceAllocationState; 22 import com.android.tradefed.device.DeviceNotAvailableException; 23 import com.android.tradefed.device.FreeDeviceState; 24 import com.android.tradefed.device.IDeviceManager; 25 import com.android.tradefed.device.ITestDevice; 26 import com.android.tradefed.invoker.IInvocationContext; 27 import com.android.tradefed.invoker.InvocationContext; 28 29 import junit.framework.TestCase; 30 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.HashMap; 34 import java.util.List; 35 import java.util.Map; 36 37 import org.easymock.EasyMock; 38 import org.easymock.IAnswer; 39 40 /** 41 * Unit tests for {@link RemoteManager}. 42 */ 43 public class RemoteManagerFuncTest extends TestCase { 44 45 private IDeviceManager mMockDeviceManager; 46 private RemoteManager mRemoteMgr; 47 private IRemoteClient mRemoteClient; 48 private ICommandScheduler mMockScheduler; 49 50 @Override setUp()51 protected void setUp() throws Exception { 52 super.setUp(); 53 mMockDeviceManager = EasyMock.createMock(IDeviceManager.class); 54 mMockScheduler = EasyMock.createMock(ICommandScheduler.class); 55 mRemoteMgr = new RemoteManager(mMockDeviceManager, mMockScheduler); 56 // Extra short timeout for testing. 57 mRemoteMgr.setRemoteManagerTimeout(100); 58 } 59 60 @Override tearDown()61 protected void tearDown() throws Exception { 62 if (mRemoteClient != null) { 63 mRemoteClient.close(); 64 } 65 if (mRemoteMgr != null) { 66 mRemoteMgr.cancelAndWait(); 67 } 68 super.tearDown(); 69 } 70 71 /** 72 * An integration test for client-manager interaction, that will allocate, then free a device. 73 */ testAllocateFree()74 public void testAllocateFree() throws Exception { 75 ITestDevice device = EasyMock.createMock(ITestDevice.class); 76 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 77 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 78 mMockDeviceManager.freeDevice(EasyMock.eq(device), 79 EasyMock.eq(FreeDeviceState.AVAILABLE)); 80 81 EasyMock.replay(mMockDeviceManager, device); 82 mRemoteMgr.connectAnyPort(); 83 mRemoteMgr.start(); 84 int port = mRemoteMgr.getPort(); 85 assertTrue(port != -1); 86 mRemoteClient = RemoteClient.connect(port); 87 mRemoteClient.sendAllocateDevice("serial"); 88 mRemoteClient.sendFreeDevice("serial"); 89 EasyMock.verify(mMockDeviceManager); 90 } 91 92 /** 93 * An integration test for client-manager interaction, that will add a command 94 */ testAddCommand()95 public void testAddCommand() throws Exception { 96 EasyMock.expect(mMockScheduler.addCommand(EasyMock.aryEq(new String[] { 97 "arg1", "arg2" 98 }), EasyMock.anyInt())).andReturn(true); 99 100 EasyMock.replay(mMockScheduler); 101 mRemoteMgr.connectAnyPort(); 102 mRemoteMgr.start(); 103 int port = mRemoteMgr.getPort(); 104 assertTrue(port != -1); 105 mRemoteClient = RemoteClient.connect(port); 106 mRemoteClient.sendAddCommand(3, "arg1", "arg2"); 107 EasyMock.verify(mMockScheduler); 108 } 109 110 /** 111 * An integration test for client-manager interaction, that will add a command file 112 */ testAddCommandFile()113 public void testAddCommandFile() throws Exception { 114 final String cmdFile = "cmd.txt"; 115 List<String> extraArgs = Arrays.asList("foo", "bar"); 116 mMockScheduler.addCommandFile(EasyMock.eq(cmdFile), EasyMock.eq(extraArgs)); 117 118 EasyMock.replay(mMockScheduler); 119 mRemoteMgr.connectAnyPort(); 120 mRemoteMgr.start(); 121 int port = mRemoteMgr.getPort(); 122 assertTrue(port != -1); 123 mRemoteClient = RemoteClient.connect(port); 124 mRemoteClient.sendAddCommandFile(cmdFile, extraArgs); 125 EasyMock.verify(mMockScheduler); 126 } 127 128 /** 129 * An integration test for client-manager interaction, that will allocate, then close the 130 * connection. Verifies that closing frees all devices. 131 */ 132 @SuppressWarnings("deprecation") testAllocateClose()133 public void testAllocateClose() throws Exception { 134 ITestDevice device = EasyMock.createMock(ITestDevice.class); 135 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 136 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 137 mMockDeviceManager.freeDevice(EasyMock.eq(device), 138 EasyMock.eq(FreeDeviceState.AVAILABLE)); 139 140 EasyMock.replay(mMockDeviceManager, device); 141 mRemoteMgr.connectAnyPort(); 142 mRemoteMgr.start(); 143 int port = mRemoteMgr.getPort(); 144 assertTrue(port != -1); 145 mRemoteClient = RemoteClient.connect(port); 146 mRemoteClient.sendAllocateDevice("serial"); 147 mRemoteClient.sendClose(); 148 mRemoteClient.close(); 149 mRemoteMgr.join(); 150 EasyMock.verify(mMockDeviceManager); 151 } 152 153 /** 154 * An integration test for client-manager interaction, that will allocate, then frees all 155 * devices. 156 */ testAllocateFreeAll()157 public void testAllocateFreeAll() throws Exception { 158 ITestDevice device = EasyMock.createMock(ITestDevice.class); 159 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 160 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 161 mMockDeviceManager.freeDevice(EasyMock.eq(device), 162 EasyMock.eq(FreeDeviceState.AVAILABLE)); 163 164 EasyMock.replay(mMockDeviceManager, device); 165 mRemoteMgr.connectAnyPort(); 166 mRemoteMgr.start(); 167 int port = mRemoteMgr.getPort(); 168 assertTrue(port != -1); 169 mRemoteClient = RemoteClient.connect(port); 170 mRemoteClient.sendAllocateDevice("serial"); 171 mRemoteClient.sendFreeDevice("*"); 172 EasyMock.verify(mMockDeviceManager); 173 } 174 175 /** 176 * Test attempt to free an unknown device 177 */ testFree_unknown()178 public void testFree_unknown() throws Exception { 179 mRemoteMgr.connectAnyPort(); 180 mRemoteMgr.start(); 181 int port = mRemoteMgr.getPort(); 182 assertTrue(port != -1); 183 mRemoteClient = RemoteClient.connect(port); 184 try { 185 mRemoteClient.sendFreeDevice("foo"); 186 fail("RemoteException not thrown"); 187 } catch (RemoteException e) { 188 // expected 189 } 190 } 191 192 /** 193 * An integration test for {@link ListDevicesOp} 194 */ testListDevices()195 public void testListDevices() throws Exception { 196 List<DeviceDescriptor> deviceList = 197 new ArrayList<DeviceDescriptor>(2); 198 deviceList.add( 199 new DeviceDescriptor( 200 "serial", 201 false, 202 DeviceAllocationState.Available, 203 "tuna", 204 "toro", 205 "18", 206 "JWR67C", 207 "4") 208 ); 209 deviceList.add( 210 new DeviceDescriptor( 211 "serial2", 212 false, 213 DeviceAllocationState.Allocated, 214 "herring", 215 "crespo", 216 "15", 217 "IMM767", 218 "5") 219 ); 220 EasyMock.expect(mMockDeviceManager.listAllDevices()).andReturn(deviceList); 221 EasyMock.replay(mMockDeviceManager); 222 mRemoteMgr.connectAnyPort(); 223 mRemoteMgr.start(); 224 int port = mRemoteMgr.getPort(); 225 assertTrue(port != -1); 226 mRemoteClient = RemoteClient.connect(port); 227 List<DeviceDescriptor> returnedDevices = mRemoteClient.sendListDevices(); 228 assertEquals(2, returnedDevices.size()); 229 assertEquals("serial", returnedDevices.get(0).getSerial()); 230 assertFalse(returnedDevices.get(0).isStubDevice()); 231 assertEquals(DeviceAllocationState.Available, returnedDevices.get(0).getState()); 232 assertEquals("tuna", returnedDevices.get(0).getProduct()); 233 assertEquals("toro", returnedDevices.get(0).getProductVariant()); 234 assertEquals("18", returnedDevices.get(0).getSdkVersion()); 235 assertEquals("JWR67C", returnedDevices.get(0).getBuildId()); 236 assertEquals("4", returnedDevices.get(0).getBatteryLevel()); 237 assertEquals("serial2", returnedDevices.get(1).getSerial()); 238 assertFalse(returnedDevices.get(1).isStubDevice()); 239 assertEquals(DeviceAllocationState.Allocated, returnedDevices.get(1).getState()); 240 assertEquals("herring", returnedDevices.get(1).getProduct()); 241 assertEquals("crespo", returnedDevices.get(1).getProductVariant()); 242 assertEquals("15", returnedDevices.get(1).getSdkVersion()); 243 assertEquals("IMM767", returnedDevices.get(1).getBuildId()); 244 assertEquals("5", returnedDevices.get(1).getBatteryLevel()); 245 EasyMock.verify(mMockDeviceManager); 246 } 247 248 /** 249 * An integration test for normal case {@link ExecCommandOp} 250 */ testExecCommand()251 public void testExecCommand() throws Exception { 252 ITestDevice device = EasyMock.createMock(ITestDevice.class); 253 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 254 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 255 mMockDeviceManager.freeDevice(EasyMock.eq(device), EasyMock.eq(FreeDeviceState.AVAILABLE)); 256 String[] args = new String[] { 257 "instrument" 258 }; 259 mMockScheduler.execCommand((IScheduledInvocationListener)EasyMock.anyObject(), 260 EasyMock.eq(device), EasyMock.aryEq(args)); 261 262 EasyMock.replay(mMockDeviceManager, device, mMockScheduler); 263 mRemoteMgr.connectAnyPort(); 264 mRemoteMgr.start(); 265 int port = mRemoteMgr.getPort(); 266 assertTrue(port != -1); 267 mRemoteClient = RemoteClient.connect(port); 268 mRemoteClient.sendAllocateDevice("serial"); 269 mRemoteClient.sendExecCommand("serial", args); 270 mRemoteClient.sendFreeDevice("serial"); 271 EasyMock.verify(mMockDeviceManager, mMockScheduler); 272 } 273 274 /** 275 * An integration test for consecutive executes {@link ExecCommandOp} 276 */ testConsecutiveExecCommand()277 public void testConsecutiveExecCommand() throws Exception { 278 final ITestDevice device = EasyMock.createMock(ITestDevice.class); 279 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 280 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 281 mMockDeviceManager.freeDevice(EasyMock.eq(device), EasyMock.eq(FreeDeviceState.AVAILABLE)); 282 String[] args = new String[] { 283 "instrument" 284 }; 285 mMockScheduler.execCommand((IScheduledInvocationListener)EasyMock.anyObject(), 286 EasyMock.eq(device), EasyMock.aryEq(args)); 287 IAnswer<Object> commandSuccessAnswer = new IAnswer<Object>() { 288 @SuppressWarnings("unchecked") 289 @Override 290 public Object answer() { 291 ExecCommandTracker commandTracker = 292 (ExecCommandTracker) EasyMock.getCurrentArguments()[0]; 293 IInvocationContext nullMeta = new InvocationContext(); 294 nullMeta.addAllocatedDevice("device", device); 295 Map<ITestDevice, FreeDeviceState> state = new HashMap<>(); 296 state.put(device, FreeDeviceState.UNAVAILABLE); 297 commandTracker.invocationComplete(nullMeta, state); 298 return null; 299 } 300 }; 301 EasyMock.expectLastCall().andAnswer(commandSuccessAnswer); 302 303 mMockScheduler.execCommand((IScheduledInvocationListener)EasyMock.anyObject(), 304 EasyMock.eq(device), EasyMock.aryEq(args)); 305 EasyMock.replay(mMockDeviceManager, device, mMockScheduler); 306 mRemoteMgr.connectAnyPort(); 307 mRemoteMgr.start(); 308 int port = mRemoteMgr.getPort(); 309 assertTrue(port != -1); 310 mRemoteClient = RemoteClient.connect(port); 311 mRemoteClient.sendAllocateDevice("serial"); 312 // First command succeeds right way. 313 mRemoteClient.sendExecCommand("serial", args); 314 // Second command will be scheduled but will not finish. 315 mRemoteClient.sendExecCommand("serial", args); 316 // Third command will fail since the second command is still executing. 317 try { 318 mRemoteClient.sendExecCommand("serial", args); 319 fail("did not receive RemoteException"); 320 } catch (RemoteException e) { 321 // expected 322 } 323 mRemoteClient.sendFreeDevice("serial"); 324 EasyMock.verify(mMockDeviceManager, mMockScheduler); 325 } 326 327 /** 328 * An integration test for case where device was not allocated before {@link ExecCommandOp} 329 */ testExecCommand_noallocate()330 public void testExecCommand_noallocate() throws Exception { 331 mRemoteMgr.connectAnyPort(); 332 mRemoteMgr.start(); 333 int port = mRemoteMgr.getPort(); 334 assertTrue(port != -1); 335 mRemoteClient = RemoteClient.connect(port); 336 try { 337 mRemoteClient.sendExecCommand("serial", new String[] {"instrument"}); 338 } catch (RemoteException e) { 339 // expected 340 return; 341 } 342 fail("did not receive RemoteException"); 343 } 344 345 /** 346 * Happy-path test for a handover start 347 */ testHandover()348 public void testHandover() throws Exception { 349 final int port = 88; 350 EasyMock.expect(mMockScheduler.handoverShutdown(port)).andReturn(Boolean.TRUE); 351 352 EasyMock.replay(mMockScheduler); 353 mRemoteMgr.connectAnyPort(); 354 mRemoteMgr.start(); 355 int mgrPort = mRemoteMgr.getPort(); 356 assertTrue(mgrPort != -1); 357 mRemoteClient = RemoteClient.connect(mgrPort); 358 mRemoteClient.sendStartHandover(port); 359 // disgusting sleep alert! TODO: change to a wait-notify thingy 360 Thread.sleep(100); 361 EasyMock.verify(mMockScheduler); 362 } 363 364 /** 365 * Basic test for a handover init complete op 366 */ testHandoverInit()367 public void testHandoverInit() throws Exception { 368 // expect 369 mMockScheduler.handoverInitiationComplete(); 370 371 EasyMock.replay(mMockScheduler); 372 mRemoteMgr.connectAnyPort(); 373 mRemoteMgr.start(); 374 int mgrPort = mRemoteMgr.getPort(); 375 assertTrue(mgrPort != -1); 376 mRemoteClient = RemoteClient.connect(mgrPort); 377 mRemoteClient.sendHandoverInitComplete(); 378 // disgusting sleep alert! TODO: change to a wait-notify thingy 379 Thread.sleep(100); 380 EasyMock.verify(mMockScheduler); 381 } 382 383 /** 384 * Test {@link GetLastCommandResultOp} result when device is unknown 385 * @throws Exception 386 */ testGetLastCommandResult_unknownDevice()387 public void testGetLastCommandResult_unknownDevice() throws Exception { 388 ICommandResultHandler mockHandler = EasyMock.createStrictMock(ICommandResultHandler.class); 389 mockHandler.notAllocated(); 390 mRemoteMgr.connectAnyPort(); 391 mRemoteMgr.start(); 392 393 int mgrPort = mRemoteMgr.getPort(); 394 assertTrue(mgrPort != -1); 395 mRemoteClient = RemoteClient.connect(mgrPort); 396 EasyMock.replay(mockHandler); 397 398 mRemoteClient.sendGetLastCommandResult("foo", mockHandler); 399 400 EasyMock.verify(mockHandler); 401 } 402 403 /** 404 * Test {@link GetLastCommandResultOp} result when there is no active command 405 */ testGetLastCommandResult_noActiveCommand()406 public void testGetLastCommandResult_noActiveCommand() throws Exception { 407 ICommandResultHandler mockHandler = EasyMock.createStrictMock(ICommandResultHandler.class); 408 mockHandler.noActiveCommand(); 409 ITestDevice device = EasyMock.createMock(ITestDevice.class); 410 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 411 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 412 mMockDeviceManager.freeDevice(EasyMock.eq(device), EasyMock.eq(FreeDeviceState.AVAILABLE)); 413 EasyMock.replay(mMockDeviceManager, device, mockHandler); 414 415 mRemoteMgr.connectAnyPort(); 416 mRemoteMgr.start(); 417 int mgrPort = mRemoteMgr.getPort(); 418 assertTrue(mgrPort != -1); 419 mRemoteClient = RemoteClient.connect(mgrPort); 420 421 mRemoteClient.sendAllocateDevice("serial"); 422 mRemoteClient.sendGetLastCommandResult("serial", mockHandler); 423 mRemoteClient.sendFreeDevice("serial"); 424 425 EasyMock.verify(mockHandler, mMockDeviceManager); 426 } 427 428 /** 429 * Test {@link GetLastCommandResultOp} result when command is executing 430 */ testGetLastCommandResult_executing()431 public void testGetLastCommandResult_executing() throws Exception { 432 ICommandResultHandler mockHandler = EasyMock.createStrictMock(ICommandResultHandler.class); 433 mockHandler.stillRunning(); 434 ITestDevice device = EasyMock.createMock(ITestDevice.class); 435 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 436 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 437 mMockDeviceManager.freeDevice(EasyMock.eq(device), EasyMock.eq(FreeDeviceState.AVAILABLE)); 438 String[] args = new String[] { 439 "instrument" 440 }; 441 mMockScheduler.execCommand((IScheduledInvocationListener)EasyMock.anyObject(), 442 EasyMock.eq(device), EasyMock.aryEq(args)); 443 444 EasyMock.replay(mMockDeviceManager, device, mMockScheduler, mockHandler); 445 mRemoteMgr.connectAnyPort(); 446 mRemoteMgr.start(); 447 int port = mRemoteMgr.getPort(); 448 assertTrue(port != -1); 449 mRemoteClient = RemoteClient.connect(port); 450 mRemoteClient.sendAllocateDevice("serial"); 451 mRemoteClient.sendExecCommand("serial", args); 452 mRemoteClient.sendGetLastCommandResult("serial", mockHandler); 453 mRemoteClient.sendFreeDevice("serial"); 454 EasyMock.verify(mMockDeviceManager, mockHandler); 455 } 456 457 /** 458 * Test {@link GetLastCommandResultOp} result when commmand fails due to a not available device. 459 */ 460 @SuppressWarnings("unchecked") testGetLastCommandResult_notAvail()461 public void testGetLastCommandResult_notAvail() throws Exception { 462 ICommandResultHandler mockHandler = EasyMock.createStrictMock(ICommandResultHandler.class); 463 mockHandler.failure((String)EasyMock.anyObject(), EasyMock.eq(FreeDeviceState.UNAVAILABLE), 464 (Map<String, String>)EasyMock.anyObject()); 465 final ITestDevice device = EasyMock.createMock(ITestDevice.class); 466 EasyMock.expect(device.getSerialNumber()).andStubReturn("serial"); 467 EasyMock.expect(mMockDeviceManager.forceAllocateDevice("serial")).andReturn(device); 468 // TODO: change to not available 469 mMockDeviceManager.freeDevice(EasyMock.eq(device), EasyMock.eq(FreeDeviceState.AVAILABLE)); 470 String[] args = new String[] { 471 "instrument" 472 }; 473 mMockScheduler.execCommand((IScheduledInvocationListener)EasyMock.anyObject(), 474 EasyMock.eq(device), EasyMock.aryEq(args)); 475 IAnswer<Void> invErrorAnswer = new IAnswer<Void>() { 476 @Override 477 public Void answer() throws Throwable { 478 IScheduledInvocationListener listener = 479 (IScheduledInvocationListener)EasyMock.getCurrentArguments()[0]; 480 IInvocationContext nullMeta = new InvocationContext(); 481 nullMeta.addAllocatedDevice("device", device); 482 nullMeta.addDeviceBuildInfo("device", new BuildInfo()); 483 listener.invocationStarted(nullMeta); 484 listener.invocationFailed(new DeviceNotAvailableException()); 485 listener.invocationEnded(1); 486 Map<ITestDevice, FreeDeviceState> state = new HashMap<>(); 487 state.put(device, FreeDeviceState.UNAVAILABLE); 488 listener.invocationComplete(nullMeta, state); 489 return null; 490 } 491 }; 492 EasyMock.expectLastCall().andAnswer(invErrorAnswer); 493 494 EasyMock.replay(mMockDeviceManager, device, mMockScheduler, mockHandler); 495 mRemoteMgr.connectAnyPort(); 496 mRemoteMgr.start(); 497 int port = mRemoteMgr.getPort(); 498 assertTrue(port != -1); 499 mRemoteClient = RemoteClient.connect(port); 500 mRemoteClient.sendAllocateDevice("serial"); 501 mRemoteClient.sendExecCommand("serial", args); 502 mRemoteClient.sendGetLastCommandResult("serial", mockHandler); 503 mRemoteClient.sendFreeDevice("serial"); 504 EasyMock.verify(mMockDeviceManager, mockHandler, mMockScheduler); 505 } 506 } 507