Home | History | Annotate | Download | only in targetprep
      1 /*
      2  * Copyright (C) 2010 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.tradefed.targetprep;
     18 
     19 import static org.junit.Assert.assertFalse;
     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.build.DeviceBuildInfo;
     25 import com.android.tradefed.build.IBuildInfo;
     26 import com.android.tradefed.build.IDeviceBuildInfo;
     27 import com.android.tradefed.command.remote.DeviceDescriptor;
     28 import com.android.tradefed.device.DeviceAllocationState;
     29 import com.android.tradefed.device.DeviceNotAvailableException;
     30 import com.android.tradefed.device.DeviceUnresponsiveException;
     31 import com.android.tradefed.device.ITestDevice;
     32 import com.android.tradefed.device.ITestDevice.RecoveryMode;
     33 import com.android.tradefed.device.TestDeviceOptions;
     34 import com.android.tradefed.host.IHostOptions;
     35 import com.android.tradefed.targetprep.IDeviceFlasher.UserDataFlashOption;
     36 import com.android.tradefed.util.FileUtil;
     37 import com.android.tradefed.util.RunUtil;
     38 
     39 import org.easymock.EasyMock;
     40 import org.junit.After;
     41 import org.junit.Before;
     42 import org.junit.Test;
     43 import org.junit.runner.RunWith;
     44 import org.junit.runners.JUnit4;
     45 
     46 import java.io.File;
     47 import java.util.Arrays;
     48 import java.util.concurrent.Semaphore;
     49 
     50 /** Unit tests for {@link DeviceFlashPreparer}. */
     51 @RunWith(JUnit4.class)
     52 public class DeviceFlashPreparerTest {
     53 
     54     private IDeviceFlasher mMockFlasher;
     55     private DeviceFlashPreparer mDeviceFlashPreparer;
     56     private ITestDevice mMockDevice;
     57     private IDeviceBuildInfo mMockBuildInfo;
     58     private IHostOptions mMockHostOptions;
     59     private File mTmpDir;
     60 
     61     @Before
     62     public void setUp() throws Exception {
     63         mMockFlasher = EasyMock.createMock(IDeviceFlasher.class);
     64         mMockDevice = EasyMock.createMock(ITestDevice.class);
     65         EasyMock.expect(mMockDevice.getSerialNumber()).andReturn("foo").anyTimes();
     66         EasyMock.expect(mMockDevice.getOptions()).andReturn(new TestDeviceOptions()).anyTimes();
     67         mMockBuildInfo = new DeviceBuildInfo("0", "");
     68         mMockBuildInfo.setDeviceImageFile(new File("foo"), "0");
     69         mMockBuildInfo.setBuildFlavor("flavor");
     70         mMockHostOptions = EasyMock.createMock(IHostOptions.class);
     71         mDeviceFlashPreparer = new DeviceFlashPreparer() {
     72             @Override
     73             protected IDeviceFlasher createFlasher(ITestDevice device) {
     74                 return mMockFlasher;
     75             }
     76 
     77             @Override
     78             int getDeviceBootPollTimeMs() {
     79                 return 100;
     80             }
     81 
     82             @Override
     83             IHostOptions getHostOptions() {
     84                 return mMockHostOptions;
     85             }
     86         };
     87         // Reset default settings
     88         mDeviceFlashPreparer.setConcurrentFlashSettings(null, null, true);
     89         mDeviceFlashPreparer.setDeviceBootTime(100);
     90         // expect this call
     91         mMockFlasher.setUserDataFlashOption(UserDataFlashOption.FLASH);
     92         mTmpDir = FileUtil.createTempDir("tmp");
     93     }
     94 
     95     @After
     96     public void tearDown() throws Exception {
     97         FileUtil.recursiveDelete(mTmpDir);
     98     }
     99 
    100     /** Simple normal case test for {@link DeviceFlashPreparer#setUp(ITestDevice, IBuildInfo)}. */
    101     @Test
    102     public void testSetup() throws Exception {
    103         doSetupExpectations();
    104         EasyMock.replay(mMockFlasher, mMockDevice);
    105         mDeviceFlashPreparer.setUp(mMockDevice, mMockBuildInfo);
    106         EasyMock.verify(mMockFlasher, mMockDevice);
    107     }
    108 
    109     /**
    110      * Set EasyMock expectations for a normal setup call
    111      */
    112     private void doSetupExpectations() throws TargetSetupError, DeviceNotAvailableException {
    113         mMockDevice.setRecoveryMode(RecoveryMode.ONLINE);
    114         mMockFlasher.overrideDeviceOptions(mMockDevice);
    115         mMockFlasher.setForceSystemFlash(false);
    116         mMockFlasher.setDataWipeSkipList(Arrays.asList(new String[]{}));
    117         mMockFlasher.flash(mMockDevice, mMockBuildInfo);
    118         mMockFlasher.setWipeTimeout(EasyMock.anyLong());
    119         mMockDevice.waitForDeviceOnline();
    120         EasyMock.expect(mMockDevice.enableAdbRoot()).andStubReturn(Boolean.TRUE);
    121         mMockDevice.setDate(null);
    122         EasyMock.expect(mMockDevice.getBuildId()).andReturn(mMockBuildInfo.getBuildId());
    123         EasyMock.expect(mMockDevice.getBuildFlavor()).andReturn(mMockBuildInfo.getBuildFlavor());
    124         EasyMock.expect(mMockDevice.isEncryptionSupported()).andStubReturn(Boolean.TRUE);
    125         EasyMock.expect(mMockDevice.isDeviceEncrypted()).andStubReturn(Boolean.FALSE);
    126         mMockDevice.clearLogcat();
    127         mMockDevice.waitForDeviceAvailable(EasyMock.anyLong());
    128         mMockDevice.setRecoveryMode(RecoveryMode.AVAILABLE);
    129         mMockDevice.postBootSetup();
    130     }
    131 
    132     /**
    133      * Test {@link DeviceFlashPreparer#setUp(ITestDevice, IBuildInfo)} when a non IDeviceBuildInfo
    134      * type is provided.
    135      */
    136     @Test
    137     public void testSetUp_nonDevice() throws Exception {
    138         try {
    139             mDeviceFlashPreparer.setUp(mMockDevice, EasyMock.createMock(IBuildInfo.class));
    140             fail("IllegalArgumentException not thrown");
    141         } catch (IllegalArgumentException e) {
    142             // expected
    143         }
    144     }
    145 
    146     /** Test {@link DeviceFlashPreparer#setUp(ITestDevice, IBuildInfo)} when build does not boot. */
    147     @Test
    148     public void testSetup_buildError() throws Exception {
    149         mMockDevice.setRecoveryMode(RecoveryMode.ONLINE);
    150         mMockFlasher.overrideDeviceOptions(mMockDevice);
    151         mMockFlasher.setForceSystemFlash(false);
    152         mMockFlasher.setDataWipeSkipList(Arrays.asList(new String[]{}));
    153         mMockFlasher.flash(mMockDevice, mMockBuildInfo);
    154         mMockFlasher.setWipeTimeout(EasyMock.anyLong());
    155         mMockDevice.waitForDeviceOnline();
    156         EasyMock.expect(mMockDevice.enableAdbRoot()).andStubReturn(Boolean.TRUE);
    157         mMockDevice.setDate(null);
    158         EasyMock.expect(mMockDevice.getBuildId()).andReturn(mMockBuildInfo.getBuildId());
    159         EasyMock.expect(mMockDevice.getBuildFlavor()).andReturn(mMockBuildInfo.getBuildFlavor());
    160         EasyMock.expect(mMockDevice.isEncryptionSupported()).andStubReturn(Boolean.TRUE);
    161         EasyMock.expect(mMockDevice.isDeviceEncrypted()).andStubReturn(Boolean.FALSE);
    162         mMockDevice.clearLogcat();
    163         mMockDevice.waitForDeviceAvailable(EasyMock.anyLong());
    164         EasyMock.expectLastCall().andThrow(new DeviceUnresponsiveException("foo", "fakeserial"));
    165         mMockDevice.setRecoveryMode(RecoveryMode.AVAILABLE);
    166         EasyMock.expect(mMockDevice.getDeviceDescriptor()).andReturn(
    167                 new DeviceDescriptor("SERIAL", false, DeviceAllocationState.Available, "unknown",
    168                         "unknown", "unknown", "unknown", "unknown"));
    169         EasyMock.replay(mMockFlasher, mMockDevice);
    170         try {
    171             mDeviceFlashPreparer.setUp(mMockDevice, mMockBuildInfo);
    172             fail("DeviceFlashPreparerTest not thrown");
    173         } catch (BuildError e) {
    174             // expected; use the general version to make absolutely sure that
    175             // DeviceFailedToBootError properly masquerades as a BuildError.
    176             assertTrue(e instanceof DeviceFailedToBootError);
    177         }
    178         EasyMock.verify(mMockFlasher, mMockDevice);
    179     }
    180 
    181     /** Ensure that the flasher instance limiting machinery is working as expected. */
    182     @Test
    183     public void testFlashLimit() throws Exception {
    184         final DeviceFlashPreparer dfp = mDeviceFlashPreparer;
    185         try {
    186             Thread waiter = new Thread() {
    187                 @Override
    188                 public void run() {
    189                     dfp.takeFlashingPermit();
    190                     dfp.returnFlashingPermit();
    191                 }
    192             };
    193             EasyMock.expect(mMockHostOptions.getConcurrentFlasherLimit()).andReturn(1).anyTimes();
    194             EasyMock.replay(mMockHostOptions);
    195             dfp.setConcurrentFlashSettings(1, new Semaphore(1), true);
    196             // take the permit; the next attempt to take the permit should block
    197             dfp.takeFlashingPermit();
    198             assertFalse(dfp.getConcurrentFlashLock().hasQueuedThreads());
    199 
    200             waiter.start();
    201             RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
    202             assertTrue("Invalid state: waiter thread is not alive", waiter.isAlive());
    203             assertTrue("No queued threads", dfp.getConcurrentFlashLock().hasQueuedThreads());
    204 
    205             dfp.returnFlashingPermit();
    206             RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
    207             assertFalse("Unexpected queued threads",
    208                     dfp.getConcurrentFlashLock().hasQueuedThreads());
    209 
    210             waiter.join(1000);
    211             assertFalse("waiter thread has not returned", waiter.isAlive());
    212         } finally {
    213             // Attempt to reset concurrent flash settings to defaults
    214             dfp.setConcurrentFlashSettings(null, null, true);
    215         }
    216     }
    217 
    218     /** Ensure that the flasher limiting respects {@link IHostOptions}. */
    219     @Test
    220     public void testFlashLimit_withHostOptions() throws Exception {
    221         final DeviceFlashPreparer dfp = mDeviceFlashPreparer;
    222         try {
    223             Thread waiter = new Thread() {
    224                 @Override
    225                 public void run() {
    226                     dfp.takeFlashingPermit();
    227                     dfp.returnFlashingPermit();
    228                 }
    229             };
    230             EasyMock.expect(mMockHostOptions.getConcurrentFlasherLimit()).andReturn(1).anyTimes();
    231             EasyMock.replay(mMockHostOptions);
    232             // take the permit; the next attempt to take the permit should block
    233             dfp.takeFlashingPermit();
    234             assertFalse(dfp.getConcurrentFlashLock().hasQueuedThreads());
    235 
    236             waiter.start();
    237             RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
    238             assertTrue("Invalid state: waiter thread is not alive", waiter.isAlive());
    239             assertTrue("No queued threads", dfp.getConcurrentFlashLock().hasQueuedThreads());
    240 
    241             dfp.returnFlashingPermit();
    242             RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
    243             assertFalse("Unexpected queued threads",
    244                     dfp.getConcurrentFlashLock().hasQueuedThreads());
    245 
    246             waiter.join(1000);
    247             assertFalse("waiter thread has not returned", waiter.isAlive());
    248             EasyMock.verify(mMockHostOptions);
    249         } finally {
    250             // Attempt to reset concurrent flash settings to defaults
    251             dfp.setConcurrentFlashSettings(null, null, true);
    252         }
    253     }
    254 
    255     /** Ensure that the flasher instance limiting machinery is working as expected. */
    256     @Test
    257     public void testUnlimitedFlashLimit() throws Exception {
    258         final DeviceFlashPreparer dfp = mDeviceFlashPreparer;
    259         try {
    260             Thread waiter = new Thread() {
    261                 @Override
    262                 public void run() {
    263                     dfp.takeFlashingPermit();
    264                     dfp.returnFlashingPermit();
    265                 }
    266             };
    267             dfp.setConcurrentFlashSettings(null, null, true);
    268             // take a permit; the next attempt to take the permit should proceed without blocking
    269             dfp.takeFlashingPermit();
    270             assertNull("Flash lock is non-null", dfp.getConcurrentFlashLock());
    271 
    272             waiter.start();
    273             RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
    274             Thread.State waiterState = waiter.getState();
    275             assertTrue("Invalid state: waiter thread hasn't started",
    276                     waiter.isAlive() || Thread.State.TERMINATED.equals(waiterState));
    277             assertNull("Flash lock is non-null", dfp.getConcurrentFlashLock());
    278 
    279             dfp.returnFlashingPermit();
    280             RunUtil.getDefault().sleep(100);  // Thread start should take <100ms
    281             assertNull("Flash lock is non-null", dfp.getConcurrentFlashLock());
    282 
    283             waiter.join(1000);
    284             assertFalse("waiter thread has not returned", waiter.isAlive());
    285         } finally {
    286             // Attempt to reset concurrent flash settings to defaults
    287             dfp.setConcurrentFlashSettings(null, null, true);
    288         }
    289     }
    290 }
    291