Home | History | Annotate | Download | only in device
      1 /*
      2  * Copyright (C) 2016 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.device;
     17 
     18 import static org.mockito.Mockito.doThrow;
     19 
     20 import com.android.ddmlib.AdbCommandRejectedException;
     21 import com.android.ddmlib.FileListingService.FileEntry;
     22 import com.android.ddmlib.IDevice;
     23 import com.android.ddmlib.IDevice.DeviceState;
     24 import com.android.ddmlib.IShellOutputReceiver;
     25 import com.android.ddmlib.ShellCommandUnresponsiveException;
     26 import com.android.ddmlib.SyncException;
     27 import com.android.ddmlib.SyncException.SyncError;
     28 import com.android.ddmlib.SyncService;
     29 import com.android.ddmlib.SyncService.ISyncProgressMonitor;
     30 import com.android.ddmlib.TimeoutException;
     31 import com.android.tradefed.build.IBuildInfo;
     32 import com.android.tradefed.command.remote.DeviceDescriptor;
     33 import com.android.tradefed.config.ConfigurationException;
     34 import com.android.tradefed.config.OptionSetter;
     35 import com.android.tradefed.log.ITestLogger;
     36 import com.android.tradefed.log.LogUtil.CLog;
     37 import com.android.tradefed.result.ByteArrayInputStreamSource;
     38 import com.android.tradefed.result.FileInputStreamSource;
     39 import com.android.tradefed.result.InputStreamSource;
     40 import com.android.tradefed.result.LogDataType;
     41 import com.android.tradefed.util.Bugreport;
     42 import com.android.tradefed.util.CommandResult;
     43 import com.android.tradefed.util.CommandStatus;
     44 import com.android.tradefed.util.FileUtil;
     45 import com.android.tradefed.util.IRunUtil;
     46 import com.android.tradefed.util.StreamUtil;
     47 
     48 import com.google.common.util.concurrent.SettableFuture;
     49 
     50 import junit.framework.TestCase;
     51 
     52 import org.easymock.EasyMock;
     53 import org.mockito.Mockito;
     54 
     55 import java.io.File;
     56 import java.io.IOException;
     57 import java.time.Clock;
     58 import java.util.ArrayList;
     59 import java.util.Arrays;
     60 import java.util.Collection;
     61 import java.util.Date;
     62 import java.util.HashMap;
     63 import java.util.List;
     64 import java.util.Map;
     65 import java.util.concurrent.TimeUnit;
     66 
     67 /**
     68  * Unit tests for {@link NativeDevice}.
     69  */
     70 public class NativeDeviceTest extends TestCase {
     71 
     72     private static final String MOCK_DEVICE_SERIAL = "serial";
     73     private static final String FAKE_NETWORK_SSID = "FakeNet";
     74     private static final String FAKE_NETWORK_PASSWORD ="FakePass";
     75 
     76     private IDevice mMockIDevice;
     77     private TestableAndroidNativeDevice mTestDevice;
     78     private IDeviceRecovery mMockRecovery;
     79     private IDeviceStateMonitor mMockStateMonitor;
     80     private IRunUtil mMockRunUtil;
     81     private IWifiHelper mMockWifi;
     82     private IDeviceMonitor mMockDvcMonitor;
     83 
     84     /**
     85      * A {@link TestDevice} that is suitable for running tests against
     86      */
     87     private class TestableAndroidNativeDevice extends NativeDevice {
     88 
     89         public boolean wasCalled = false;
     90 
     91         public TestableAndroidNativeDevice() {
     92             super(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
     93         }
     94 
     95         @Override
     96         public void postBootSetup() {
     97             // too annoying to mock out postBootSetup actions everyone, so do nothing
     98         }
     99 
    100         @Override
    101         protected IRunUtil getRunUtil() {
    102             return mMockRunUtil;
    103         }
    104     }
    105 
    106     /**
    107      * {@inheritDoc}
    108      */
    109     @Override
    110     protected void setUp() throws Exception {
    111         super.setUp();
    112         mMockIDevice = EasyMock.createMock(IDevice.class);
    113         EasyMock.expect(mMockIDevice.getSerialNumber()).andReturn(MOCK_DEVICE_SERIAL).anyTimes();
    114         mMockRecovery = EasyMock.createMock(IDeviceRecovery.class);
    115         mMockStateMonitor = EasyMock.createMock(IDeviceStateMonitor.class);
    116         mMockDvcMonitor = EasyMock.createMock(IDeviceMonitor.class);
    117         mMockRunUtil = EasyMock.createMock(IRunUtil.class);
    118         mMockWifi = EasyMock.createMock(IWifiHelper.class);
    119         mMockWifi.cleanUp();
    120         EasyMock.expectLastCall().anyTimes();
    121 
    122         // A TestDevice with a no-op recoverDevice() implementation
    123         mTestDevice = new TestableAndroidNativeDevice() {
    124             @Override
    125             public void recoverDevice() throws DeviceNotAvailableException {
    126                 // ignore
    127             }
    128 
    129             @Override
    130             public IDevice getIDevice() {
    131                 return mMockIDevice;
    132             }
    133 
    134             @Override
    135             IWifiHelper createWifiHelper() {
    136                 return mMockWifi;
    137             }
    138         };
    139         mTestDevice.setRecovery(mMockRecovery);
    140         mTestDevice.setCommandTimeout(100);
    141         mTestDevice.setLogStartDelay(-1);
    142     }
    143 
    144     /**
    145      * Test return exception for package installation
    146      * {@link NativeDevice#installPackage(File, boolean, String...)}.
    147      */
    148     public void testInstallPackages_exception() {
    149         try {
    150             mTestDevice.installPackage(new File(""), false);
    151         } catch (UnsupportedOperationException onse) {
    152             return;
    153         } catch (DeviceNotAvailableException e) {
    154             fail("installPackage should have thrown an Unsupported exception, not dnae");
    155         }
    156         fail("installPackage should have thrown an exception");
    157     }
    158 
    159     /**
    160      * Test return exception for package installation
    161      * {@link NativeDevice#uninstallPackage(String)}.
    162      */
    163     public void testUninstallPackages_exception() {
    164         try {
    165             mTestDevice.uninstallPackage("");
    166         } catch (UnsupportedOperationException onse) {
    167             return;
    168         } catch (DeviceNotAvailableException e) {
    169             fail("uninstallPackage should have thrown an Unsupported exception, not dnae");
    170         }
    171         fail("uninstallPackageForUser should have thrown an exception");
    172     }
    173 
    174     /**
    175      * Test return exception for package installation
    176      * {@link NativeDevice#installPackage(File, boolean, boolean, String...)}.
    177      */
    178     public void testInstallPackagesBool_exception() {
    179         try {
    180             mTestDevice.installPackage(new File(""), false, false);
    181         } catch (UnsupportedOperationException onse) {
    182             return;
    183         } catch (DeviceNotAvailableException e) {
    184             fail("installPackage should have thrown an Unsupported exception, not dnae");
    185         }
    186         fail("installPackage should have thrown an exception");
    187     }
    188 
    189     /**
    190      * Test return exception for package installation
    191      * {@link NativeDevice#installPackageForUser(File, boolean, int, String...)}.
    192      */
    193     public void testInstallPackagesForUser_exception() {
    194         try {
    195             mTestDevice.installPackageForUser(new File(""), false, 0);
    196         } catch (UnsupportedOperationException onse) {
    197             return;
    198         } catch (DeviceNotAvailableException e) {
    199             fail("installPackageForUser should have thrown an Unsupported exception, not dnae");
    200         }
    201         fail("installPackageForUser should have thrown an exception");
    202     }
    203 
    204     /**
    205      * Test return exception for package installation
    206      * {@link NativeDevice#installPackageForUser(File, boolean, boolean, int, String...)}.
    207      */
    208     public void testInstallPackagesForUserWithPermission_exception() {
    209         try {
    210             mTestDevice.installPackageForUser(new File(""), false, false, 0);
    211         } catch (UnsupportedOperationException onse) {
    212             return;
    213         } catch (DeviceNotAvailableException e) {
    214             fail("installPackageForUser should have thrown an Unsupported exception, not dnae");
    215         }
    216         fail("installPackageForUser should have thrown an exception");
    217     }
    218 
    219     /**
    220      * Unit test for {@link NativeDevice#getInstalledPackageNames()}.
    221      */
    222     public void testGetInstalledPackageNames_exception() throws Exception {
    223         try {
    224             mTestDevice.getInstalledPackageNames();
    225         } catch (UnsupportedOperationException onse) {
    226             return;
    227         }
    228         fail("getInstalledPackageNames should have thrown an exception");
    229     }
    230 
    231     /**
    232      * Unit test for {@link NativeDevice#getScreenshot()}.
    233      */
    234     public void testGetScreenshot_exception() throws Exception {
    235         try {
    236             mTestDevice.getScreenshot();
    237         } catch (UnsupportedOperationException onse) {
    238             return;
    239         }
    240         fail("getScreenshot should have thrown an exception");
    241     }
    242 
    243     /**
    244      * Unit test for {@link NativeDevice#pushDir(File, String)}.
    245      */
    246     public void testPushDir_notADir() throws Exception {
    247         assertFalse(mTestDevice.pushDir(new File(""), ""));
    248     }
    249 
    250     /**
    251      * Unit test for {@link NativeDevice#pushDir(File, String)}.
    252      */
    253     public void testPushDir_childFile() throws Exception {
    254         mTestDevice = new TestableAndroidNativeDevice() {
    255             @Override
    256             public boolean pushFile(File localFile, String remoteFilePath)
    257                     throws DeviceNotAvailableException {
    258                 return true;
    259             }
    260         };
    261         File testDir = FileUtil.createTempDir("pushDirTest");
    262         FileUtil.createTempFile("test1", ".txt", testDir);
    263         assertTrue(mTestDevice.pushDir(testDir, ""));
    264         FileUtil.recursiveDelete(testDir);
    265     }
    266 
    267     /**
    268      * Unit test for {@link NativeDevice#pushDir(File, String)}.
    269      */
    270     public void testPushDir_childDir() throws Exception {
    271         mTestDevice = new TestableAndroidNativeDevice() {
    272             @Override
    273             public String executeShellCommand(String cmd) throws DeviceNotAvailableException {
    274                 return "";
    275             }
    276             @Override
    277             public boolean pushFile(File localFile, String remoteFilePath)
    278                     throws DeviceNotAvailableException {
    279                 return false;
    280             }
    281         };
    282         File testDir = FileUtil.createTempDir("pushDirTest");
    283         File subDir = FileUtil.createTempDir("testSubDir", testDir);
    284         FileUtil.createTempDir("test1", subDir);
    285         assertTrue(mTestDevice.pushDir(testDir, ""));
    286         FileUtil.recursiveDelete(testDir);
    287     }
    288 
    289     /** Test {@link NativeDevice#pullDir(String, File)} when the remote directory is empty. */
    290     public void testPullDir_nothingToDo() throws Exception {
    291         final IFileEntry fakeEntry = EasyMock.createMock(IFileEntry.class);
    292         mTestDevice =
    293                 new TestableAndroidNativeDevice() {
    294                     @Override
    295                     public IFileEntry getFileEntry(FileEntry path)
    296                             throws DeviceNotAvailableException {
    297                         return fakeEntry;
    298                     }
    299 
    300                     @Override
    301                     public String executeShellCommand(String command)
    302                             throws DeviceNotAvailableException {
    303                         return "drwxr-xr-x root     root    somedirectory";
    304                     }
    305                 };
    306         File dir = FileUtil.createTempDir("tf-test");
    307         Collection<IFileEntry> childrens = new ArrayList<>();
    308         EasyMock.expect(fakeEntry.getChildren(false)).andReturn(childrens);
    309         // Empty list of childen
    310         EasyMock.replay(fakeEntry);
    311         try {
    312             boolean res = mTestDevice.pullDir("/sdcard/screenshots/", dir);
    313             assertTrue(res);
    314             assertTrue(dir.list().length == 0);
    315         } finally {
    316             FileUtil.recursiveDelete(dir);
    317         }
    318         EasyMock.verify(fakeEntry);
    319     }
    320 
    321     /**
    322      * Test {@link NativeDevice#pullDir(String, File)} when the remote directory has a file and a
    323      * directory.
    324      */
    325     public void testPullDir() throws Exception {
    326         final IFileEntry fakeEntry = EasyMock.createMock(IFileEntry.class);
    327         final IFileEntry fakeDir = EasyMock.createMock(IFileEntry.class);
    328         mTestDevice =
    329                 new TestableAndroidNativeDevice() {
    330                     private boolean mFirstCall = true;
    331 
    332                     @Override
    333                     public IFileEntry getFileEntry(FileEntry path)
    334                             throws DeviceNotAvailableException {
    335                         if (mFirstCall) {
    336                             mFirstCall = false;
    337                             return fakeEntry;
    338                         } else {
    339                             return fakeDir;
    340                         }
    341                     }
    342 
    343                     @Override
    344                     public String executeShellCommand(String command)
    345                             throws DeviceNotAvailableException {
    346                         return "drwxr-xr-x root     root    somedirectory";
    347                     }
    348 
    349                     @Override
    350                     public boolean pullFile(String remoteFilePath, File localFile)
    351                             throws DeviceNotAvailableException {
    352                         try {
    353                             // Just touch the file to make it appear.
    354                             localFile.createNewFile();
    355                         } catch (IOException e) {
    356                             throw new RuntimeException(e);
    357                         }
    358                         return true;
    359                     }
    360                 };
    361         File dir = FileUtil.createTempDir("tf-test");
    362         Collection<IFileEntry> children = new ArrayList<>();
    363         IFileEntry fakeFile = EasyMock.createMock(IFileEntry.class);
    364         children.add(fakeFile);
    365         EasyMock.expect(fakeFile.isDirectory()).andReturn(false);
    366         EasyMock.expect(fakeFile.getName()).andReturn("fakeFile");
    367         EasyMock.expect(fakeFile.getFullPath()).andReturn("/sdcard/screenshots/fakeFile");
    368 
    369         children.add(fakeDir);
    370         EasyMock.expect(fakeDir.isDirectory()).andReturn(true);
    371         EasyMock.expect(fakeDir.getName()).andReturn("fakeDir");
    372         EasyMock.expect(fakeDir.getFullPath()).andReturn("/sdcard/screenshots/fakeDir");
    373         // #pullDir is being called on dir fakeDir to pull everything recursively.
    374         Collection<IFileEntry> fakeDirChildren = new ArrayList<>();
    375         EasyMock.expect(fakeDir.getChildren(false)).andReturn(fakeDirChildren);
    376         EasyMock.expect(fakeEntry.getChildren(false)).andReturn(children);
    377 
    378         EasyMock.replay(fakeEntry, fakeFile, fakeDir);
    379         try {
    380             boolean res = mTestDevice.pullDir("/sdcard/screenshots/", dir);
    381             assertTrue(res);
    382             assertEquals(2, dir.list().length);
    383             assertTrue(Arrays.asList(dir.list()).contains("fakeFile"));
    384             assertTrue(Arrays.asList(dir.list()).contains("fakeDir"));
    385         } finally {
    386             FileUtil.recursiveDelete(dir);
    387         }
    388         EasyMock.verify(fakeEntry, fakeFile, fakeDir);
    389     }
    390 
    391     /** Test pulling a directory when one of the pull fails. */
    392     public void testPullDir_pullFail() throws Exception {
    393         final IFileEntry fakeEntry = EasyMock.createMock(IFileEntry.class);
    394         final IFileEntry fakeDir = EasyMock.createMock(IFileEntry.class);
    395         mTestDevice =
    396                 new TestableAndroidNativeDevice() {
    397                     private boolean mFirstCall = true;
    398                     private boolean mFirstPull = true;
    399 
    400                     @Override
    401                     public IFileEntry getFileEntry(FileEntry path)
    402                             throws DeviceNotAvailableException {
    403                         if (mFirstCall) {
    404                             mFirstCall = false;
    405                             return fakeEntry;
    406                         } else {
    407                             return fakeDir;
    408                         }
    409                     }
    410 
    411                     @Override
    412                     public String executeShellCommand(String command)
    413                             throws DeviceNotAvailableException {
    414                         return "drwxr-xr-x root     root    somedirectory";
    415                     }
    416 
    417                     @Override
    418                     public boolean pullFile(String remoteFilePath, File localFile)
    419                             throws DeviceNotAvailableException {
    420                         if (mFirstPull) {
    421                             mFirstPull = false;
    422                             try {
    423                                 // Just touch the file to make it appear.
    424                                 localFile.createNewFile();
    425                             } catch (IOException e) {
    426                                 throw new RuntimeException(e);
    427                             }
    428                             return true;
    429                         } else {
    430                             return false;
    431                         }
    432                     }
    433                 };
    434         File dir = FileUtil.createTempDir("tf-test");
    435         Collection<IFileEntry> children = new ArrayList<>();
    436         IFileEntry fakeFile = EasyMock.createMock(IFileEntry.class);
    437         children.add(fakeFile);
    438         EasyMock.expect(fakeFile.isDirectory()).andReturn(false);
    439         EasyMock.expect(fakeFile.getName()).andReturn("fakeFile");
    440         EasyMock.expect(fakeFile.getFullPath()).andReturn("/sdcard/screenshots/fakeFile");
    441 
    442         children.add(fakeDir);
    443         EasyMock.expect(fakeDir.isDirectory()).andReturn(true);
    444         EasyMock.expect(fakeDir.getName()).andReturn("fakeDir");
    445         EasyMock.expect(fakeDir.getFullPath()).andReturn("/sdcard/screenshots/fakeDir");
    446         // #pullDir is being called on dir fakeDir to pull everything recursively.
    447         Collection<IFileEntry> fakeDirChildren = new ArrayList<>();
    448         IFileEntry secondLevelChildren = EasyMock.createMock(IFileEntry.class);
    449         fakeDirChildren.add(secondLevelChildren);
    450         EasyMock.expect(fakeDir.getChildren(false)).andReturn(fakeDirChildren);
    451         EasyMock.expect(fakeEntry.getChildren(false)).andReturn(children);
    452 
    453         EasyMock.expect(secondLevelChildren.isDirectory()).andReturn(false);
    454         EasyMock.expect(secondLevelChildren.getName()).andReturn("secondLevelChildren");
    455         EasyMock.expect(secondLevelChildren.getFullPath())
    456                 .andReturn("/sdcard/screenshots/fakeDir/secondLevelChildren");
    457 
    458         EasyMock.replay(fakeEntry, fakeFile, fakeDir, secondLevelChildren);
    459         try {
    460             boolean res = mTestDevice.pullDir("/sdcard/screenshots/", dir);
    461             // If one of the pull fails, the full command is considered failed.
    462             assertFalse(res);
    463             assertEquals(2, dir.list().length);
    464             assertTrue(Arrays.asList(dir.list()).contains("fakeFile"));
    465             // The subdir was created
    466             assertTrue(Arrays.asList(dir.list()).contains("fakeDir"));
    467             // The last file failed to pull, so the dir is empty.
    468             assertEquals(0, new File(dir, "fakeDir").list().length);
    469         } finally {
    470             FileUtil.recursiveDelete(dir);
    471         }
    472         EasyMock.verify(fakeEntry, fakeFile, fakeDir, secondLevelChildren);
    473     }
    474 
    475     /**
    476      * Test that if the requested path is not a directory on the device side, we just fail directly.
    477      */
    478     public void testPullDir_invalidPath() throws Exception {
    479         mTestDevice =
    480                 new TestableAndroidNativeDevice() {
    481                     @Override
    482                     public String executeShellCommand(String command)
    483                             throws DeviceNotAvailableException {
    484                         return "-rwxr-xr-x root     root    somefile";
    485                     }
    486                 };
    487         File dir = FileUtil.createTempDir("tf-test");
    488         try {
    489             assertFalse(mTestDevice.pullDir("somefile", dir));
    490             assertTrue(dir.list().length == 0);
    491         } finally {
    492             FileUtil.recursiveDelete(dir);
    493         }
    494     }
    495 
    496     /**
    497      * Unit test for {@link NativeDevice#getCurrentUser()}.
    498      */
    499     public void testGetCurrentUser_exception() throws Exception {
    500         try {
    501             mTestDevice.getScreenshot();
    502         } catch (UnsupportedOperationException onse) {
    503             return;
    504         }
    505         fail("getCurrentUser should have thrown an exception.");
    506     }
    507 
    508     /**
    509      * Unit test for {@link NativeDevice#getUserFlags(int)}.
    510      */
    511     public void testGetUserFlags_exception() throws Exception {
    512         try {
    513             mTestDevice.getUserFlags(0);
    514         } catch (UnsupportedOperationException onse) {
    515             return;
    516         }
    517         fail("getUserFlags should have thrown an exception.");
    518     }
    519 
    520     /**
    521      * Unit test for {@link NativeDevice#getUserSerialNumber(int)}.
    522      */
    523     public void testGetUserSerialNumber_exception() throws Exception {
    524         try {
    525             mTestDevice.getUserSerialNumber(0);
    526         } catch (UnsupportedOperationException onse) {
    527             return;
    528         }
    529         fail("getUserSerialNumber should have thrown an exception.");
    530     }
    531 
    532     /**
    533      * Unit test for {@link NativeDevice#switchUser(int)}.
    534      */
    535     public void testSwitchUser_exception() throws Exception {
    536         try {
    537             mTestDevice.switchUser(10);
    538         } catch (UnsupportedOperationException onse) {
    539             return;
    540         }
    541         fail("switchUser should have thrown an exception.");
    542     }
    543 
    544     /**
    545      * Unit test for {@link NativeDevice#switchUser(int, long)}.
    546      */
    547     public void testSwitchUserTimeout_exception() throws Exception {
    548         try {
    549             mTestDevice.switchUser(10, 5*1000);
    550         } catch (UnsupportedOperationException onse) {
    551             return;
    552         }
    553         fail("switchUser should have thrown an exception.");
    554     }
    555 
    556     /**
    557      * Unit test for {@link NativeDevice#stopUser(int)}.
    558      */
    559     public void testStopUser_exception() throws Exception {
    560         try {
    561             mTestDevice.stopUser(0);
    562         } catch (UnsupportedOperationException onse) {
    563             return;
    564         }
    565         fail("stopUser should have thrown an exception.");
    566     }
    567 
    568     /**
    569      * Unit test for {@link NativeDevice#stopUser(int, boolean, boolean)}.
    570      */
    571     public void testStopUserFlags_exception() throws Exception {
    572         try {
    573             mTestDevice.stopUser(0, true, true);
    574         } catch (UnsupportedOperationException onse) {
    575             return;
    576         }
    577         fail("stopUser should have thrown an exception.");
    578     }
    579 
    580     /**
    581      * Unit test for {@link NativeDevice#isUserRunning(int)}.
    582      */
    583     public void testIsUserIdRunning_exception() throws Exception {
    584         try {
    585             mTestDevice.isUserRunning(0);
    586         } catch (UnsupportedOperationException onse) {
    587             return;
    588         }
    589         fail("stopUser should have thrown an exception.");
    590     }
    591 
    592     /**
    593      * Unit test for {@link NativeDevice#hasFeature(String)}.
    594      */
    595     public void testHasFeature_exception() throws Exception {
    596         try {
    597             mTestDevice.hasFeature("feature:test");
    598         } catch (UnsupportedOperationException onse) {
    599             return;
    600         }
    601         fail("hasFeature should have thrown an exception.");
    602     }
    603 
    604     /**
    605      * Unit test for {@link NativeDevice#getSetting(String, String)}.
    606      */
    607     public void testGetSettingSystemUser_exception() throws Exception {
    608         try {
    609             mTestDevice.getSetting("global", "wifi_on");
    610         } catch (UnsupportedOperationException onse) {
    611             return;
    612         }
    613         fail("getSettings should have thrown an exception.");
    614     }
    615 
    616     /**
    617      * Unit test for {@link NativeDevice#getSetting(int, String, String)}.
    618      */
    619     public void testGetSetting_exception() throws Exception {
    620         try {
    621             mTestDevice.getSetting(0, "global", "wifi_on");
    622         } catch (UnsupportedOperationException onse) {
    623             return;
    624         }
    625         fail("getSettings should have thrown an exception.");
    626     }
    627 
    628     /**
    629      * Unit test for {@link NativeDevice#setSetting(String, String, String)}.
    630      */
    631     public void testSetSettingSystemUser_exception() throws Exception {
    632         try {
    633             mTestDevice.setSetting("global", "wifi_on", "0");
    634         } catch (UnsupportedOperationException onse) {
    635             return;
    636         }
    637         fail("putSettings should have thrown an exception.");
    638     }
    639 
    640     /**
    641      * Unit test for {@link NativeDevice#setSetting(int, String, String, String)}.
    642      */
    643     public void testSetSetting_exception() throws Exception {
    644         try {
    645             mTestDevice.setSetting(0, "global", "wifi_on", "0");
    646         } catch (UnsupportedOperationException onse) {
    647             return;
    648         }
    649         fail("putSettings should have thrown an exception.");
    650     }
    651 
    652     /**
    653      * Unit test for {@link NativeDevice#getAndroidId(int)}.
    654      */
    655     public void testGetAndroidId_exception() throws Exception {
    656         try {
    657             mTestDevice.getAndroidId(0);
    658         } catch (UnsupportedOperationException onse) {
    659             return;
    660         }
    661         fail("getAndroidId should have thrown an exception.");
    662     }
    663 
    664     /**
    665      * Unit test for {@link NativeDevice#getAndroidIds()}.
    666      */
    667     public void testGetAndroidIds_exception() throws Exception {
    668         try {
    669             mTestDevice.getAndroidIds();
    670         } catch (UnsupportedOperationException onse) {
    671             return;
    672         }
    673         fail("getAndroidIds should have thrown an exception.");
    674     }
    675 
    676     /**
    677      * Unit test for {@link NativeDevice#connectToWifiNetworkIfNeeded(String, String)}.
    678      */
    679     public void testConnectToWifiNetworkIfNeeded_alreadyConnected()
    680             throws DeviceNotAvailableException {
    681         EasyMock.expect(mMockWifi.checkConnectivity(mTestDevice.getOptions().getConnCheckUrl()))
    682                 .andReturn(true);
    683         EasyMock.replay(mMockWifi);
    684         assertTrue(mTestDevice.connectToWifiNetworkIfNeeded(FAKE_NETWORK_SSID,
    685                 FAKE_NETWORK_PASSWORD));
    686         EasyMock.verify(mMockWifi);
    687     }
    688 
    689     /**
    690      * Unit test for {@link NativeDevice#connectToWifiNetwork(String, String)}.
    691      */
    692     public void testConnectToWifiNetwork_success() throws DeviceNotAvailableException {
    693         EasyMock.expect(mMockWifi.connectToNetwork(FAKE_NETWORK_SSID, FAKE_NETWORK_PASSWORD,
    694                 mTestDevice.getOptions().getConnCheckUrl(), false)).andReturn(true);
    695         Map<String, String> fakeWifiInfo = new HashMap<String, String>();
    696         fakeWifiInfo.put("bssid", FAKE_NETWORK_SSID);
    697         EasyMock.expect(mMockWifi.getWifiInfo()).andReturn(fakeWifiInfo);
    698         EasyMock.replay(mMockWifi, mMockIDevice);
    699         assertTrue(mTestDevice.connectToWifiNetwork(FAKE_NETWORK_SSID,
    700                 FAKE_NETWORK_PASSWORD));
    701         EasyMock.verify(mMockWifi, mMockIDevice);
    702     }
    703 
    704     /**
    705      * Unit test for {@link NativeDevice#connectToWifiNetwork(String, String)} for a failure
    706      * to connect case.
    707      */
    708     public void testConnectToWifiNetwork_failure() throws DeviceNotAvailableException {
    709         EasyMock.expect(mMockWifi.connectToNetwork(FAKE_NETWORK_SSID, FAKE_NETWORK_PASSWORD,
    710                 mTestDevice.getOptions().getConnCheckUrl(), false)).andReturn(false)
    711                 .times(mTestDevice.getOptions().getWifiAttempts());
    712         Map<String, String> fakeWifiInfo = new HashMap<String, String>();
    713         fakeWifiInfo.put("bssid", FAKE_NETWORK_SSID);
    714         EasyMock.expect(mMockWifi.getWifiInfo()).andReturn(fakeWifiInfo)
    715                 .times(mTestDevice.getOptions().getWifiAttempts());
    716         mMockRunUtil.sleep(EasyMock.anyLong());
    717         EasyMock.expectLastCall().times(mTestDevice.getOptions().getWifiAttempts() - 1);
    718         EasyMock.replay(mMockWifi, mMockIDevice, mMockRunUtil);
    719         assertFalse(mTestDevice.connectToWifiNetwork(FAKE_NETWORK_SSID,
    720                 FAKE_NETWORK_PASSWORD));
    721         EasyMock.verify(mMockWifi, mMockIDevice, mMockRunUtil);
    722     }
    723 
    724     /**
    725      * Unit test for {@link NativeDevice#connectToWifiNetwork(String, String)} for limiting the time
    726      * trying to connect to wifi.
    727      */
    728     public void testConnectToWifiNetwork_maxConnectTime()
    729             throws DeviceNotAvailableException, ConfigurationException {
    730         OptionSetter deviceOptionSetter = new OptionSetter(mTestDevice.getOptions());
    731         deviceOptionSetter.setOptionValue("max-wifi-connect-time", "10000");
    732         Clock mockClock = Mockito.mock(Clock.class);
    733         mTestDevice.setClock(mockClock);
    734         EasyMock.expect(
    735                         mMockWifi.connectToNetwork(
    736                                 FAKE_NETWORK_SSID,
    737                                 FAKE_NETWORK_PASSWORD,
    738                                 mTestDevice.getOptions().getConnCheckUrl(),
    739                                 false))
    740                 .andReturn(false)
    741                 .times(2);
    742         Mockito.when(mockClock.millis())
    743                 .thenReturn(Long.valueOf(0), Long.valueOf(6000), Long.valueOf(12000));
    744         Map<String, String> fakeWifiInfo = new HashMap<String, String>();
    745         fakeWifiInfo.put("bssid", FAKE_NETWORK_SSID);
    746         EasyMock.expect(mMockWifi.getWifiInfo()).andReturn(fakeWifiInfo).times(2);
    747 
    748         EasyMock.replay(mMockWifi, mMockIDevice);
    749         assertFalse(mTestDevice.connectToWifiNetwork(FAKE_NETWORK_SSID, FAKE_NETWORK_PASSWORD));
    750         EasyMock.verify(mMockWifi, mMockIDevice);
    751         Mockito.verify(mockClock, Mockito.times(3)).millis();
    752     }
    753 
    754     /**
    755      * Unit test for {@link NativeDevice#connectToWifiNetwork(String, String, boolean)}.
    756      */
    757     public void testConnectToWifiNetwork_scanSsid() throws DeviceNotAvailableException {
    758         EasyMock.expect(mMockWifi.connectToNetwork(FAKE_NETWORK_SSID, FAKE_NETWORK_PASSWORD,
    759                 mTestDevice.getOptions().getConnCheckUrl(), true)).andReturn(true);
    760         Map<String, String> fakeWifiInfo = new HashMap<String, String>();
    761         fakeWifiInfo.put("bssid", FAKE_NETWORK_SSID);
    762         EasyMock.expect(mMockWifi.getWifiInfo()).andReturn(fakeWifiInfo);
    763         EasyMock.replay(mMockWifi, mMockIDevice);
    764         assertTrue(mTestDevice.connectToWifiNetwork(FAKE_NETWORK_SSID,
    765                 FAKE_NETWORK_PASSWORD, true));
    766         EasyMock.verify(mMockWifi, mMockIDevice);
    767     }
    768 
    769     /**
    770      * Unit test for {@link NativeDevice#checkWifiConnection(String)}.
    771      */
    772     public void testCheckWifiConnection() throws DeviceNotAvailableException {
    773         EasyMock.expect(mMockWifi.isWifiEnabled()).andReturn(true);
    774         EasyMock.expect(mMockWifi.getSSID()).andReturn("\"" + FAKE_NETWORK_SSID + "\"");
    775         EasyMock.expect(mMockWifi.hasValidIp()).andReturn(true);
    776         EasyMock.expect(mMockWifi.checkConnectivity(mTestDevice.getOptions().getConnCheckUrl()))
    777                 .andReturn(true);
    778         EasyMock.replay(mMockWifi, mMockIDevice);
    779         assertTrue(mTestDevice.checkWifiConnection(FAKE_NETWORK_SSID));
    780         EasyMock.verify(mMockWifi, mMockIDevice);
    781     }
    782 
    783     /**
    784      * Unit test for {@link NativeDevice#checkWifiConnection(String)} for a failure.
    785      */
    786     public void testCheckWifiConnection_failure() throws DeviceNotAvailableException {
    787         EasyMock.expect(mMockWifi.isWifiEnabled()).andReturn(false);
    788         EasyMock.replay(mMockWifi, mMockIDevice);
    789         assertFalse(mTestDevice.checkWifiConnection(FAKE_NETWORK_SSID));
    790         EasyMock.verify(mMockWifi, mMockIDevice);
    791     }
    792 
    793     /**
    794      * Unit test for {@link NativeDevice#isWifiEnabled()}.
    795      */
    796     public void testIsWifiEnabled() throws DeviceNotAvailableException {
    797         EasyMock.expect(mMockWifi.isWifiEnabled()).andReturn(true);
    798         EasyMock.replay(mMockWifi, mMockIDevice);
    799         assertTrue(mTestDevice.isWifiEnabled());
    800         EasyMock.verify(mMockWifi, mMockIDevice);
    801     }
    802 
    803     /**
    804      * Unit test for {@link NativeDevice#isWifiEnabled()} with runtime exception from
    805      * wifihelper.
    806      */
    807     public void testIsWifiEnabled_exception() throws DeviceNotAvailableException {
    808         EasyMock.expect(mMockWifi.isWifiEnabled()).andThrow(new RuntimeException());
    809         EasyMock.replay(mMockWifi, mMockIDevice);
    810         assertFalse(mTestDevice.isWifiEnabled());
    811         EasyMock.verify(mMockWifi, mMockIDevice);
    812     }
    813 
    814     /**
    815      * Unit test for {@link NativeDevice#disconnectFromWifi()}.
    816      */
    817     public void testDisconnectFromWifi() throws DeviceNotAvailableException {
    818         EasyMock.expect(mMockWifi.disconnectFromNetwork()).andReturn(true);
    819         EasyMock.replay(mMockWifi, mMockIDevice);
    820         assertTrue(mTestDevice.disconnectFromWifi());
    821         EasyMock.verify(mMockWifi, mMockIDevice);
    822     }
    823 
    824     /**
    825      * Unit test for {@link NativeDevice#enableNetworkMonitor()}.
    826      */
    827     public void testEnableNetworkMonitor() throws DeviceNotAvailableException {
    828         EasyMock.expect(mMockWifi.stopMonitor()).andReturn(null);
    829         EasyMock.expect(mMockWifi.startMonitor(EasyMock.anyLong(),
    830                 EasyMock.eq(mTestDevice.getOptions().getConnCheckUrl()))).andReturn(true);
    831         EasyMock.replay(mMockWifi, mMockIDevice);
    832         assertTrue(mTestDevice.enableNetworkMonitor());
    833         EasyMock.verify(mMockWifi, mMockIDevice);
    834     }
    835 
    836     /**
    837      * Unit test for {@link NativeDevice#enableNetworkMonitor()} in case of failure.
    838      */
    839     public void testEnableNetworkMonitor_failure() throws DeviceNotAvailableException {
    840         EasyMock.expect(mMockWifi.stopMonitor()).andReturn(null);
    841         EasyMock.expect(mMockWifi.startMonitor(EasyMock.anyLong(),
    842                 EasyMock.eq(mTestDevice.getOptions().getConnCheckUrl()))).andReturn(false);
    843         EasyMock.replay(mMockWifi, mMockIDevice);
    844         assertFalse(mTestDevice.enableNetworkMonitor());
    845         EasyMock.verify(mMockWifi, mMockIDevice);
    846     }
    847 
    848     /**
    849      * Unit test for {@link NativeDevice#disableNetworkMonitor()}.
    850      */
    851     public void testDisableNetworkMonitor() throws DeviceNotAvailableException {
    852         List<Long> samples = new ArrayList<Long>();
    853         samples.add(Long.valueOf(42));
    854         samples.add(Long.valueOf(256));
    855         samples.add(Long.valueOf(-1)); // failure to connect
    856         EasyMock.expect(mMockWifi.stopMonitor()).andReturn(samples);
    857         EasyMock.replay(mMockWifi, mMockIDevice);
    858         assertTrue(mTestDevice.disableNetworkMonitor());
    859         EasyMock.verify(mMockWifi, mMockIDevice);
    860     }
    861 
    862     /**
    863      * Unit test for {@link NativeDevice#reconnectToWifiNetwork()}.
    864      */
    865     public void testReconnectToWifiNetwork() throws DeviceNotAvailableException {
    866         EasyMock.expect(mMockWifi.checkConnectivity(mTestDevice.getOptions().getConnCheckUrl()))
    867                 .andReturn(false);
    868         EasyMock.expect(mMockWifi.checkConnectivity(mTestDevice.getOptions().getConnCheckUrl()))
    869                 .andReturn(true);
    870         mMockRunUtil.sleep(EasyMock.anyLong());
    871         EasyMock.expectLastCall();
    872         EasyMock.replay(mMockWifi, mMockIDevice, mMockRunUtil);
    873         try {
    874             mTestDevice.reconnectToWifiNetwork();
    875         } catch (NetworkNotAvailableException nnae) {
    876             fail("reconnectToWifiNetwork() should not have thrown an exception.");
    877         } finally {
    878             EasyMock.verify(mMockWifi, mMockIDevice, mMockRunUtil);
    879         }
    880     }
    881 
    882     /**
    883      * Unit test for {@link NativeDevice#isHeadless()}.
    884      */
    885     public void testIsHeadless() throws DeviceNotAvailableException {
    886         mTestDevice = new TestableAndroidNativeDevice() {
    887             @Override
    888             public String getProperty(String name) throws DeviceNotAvailableException {
    889                 return "1\n";
    890             }
    891         };
    892         assertTrue(mTestDevice.isHeadless());
    893     }
    894 
    895     /**
    896      * Unit test for {@link NativeDevice#isHeadless()}.
    897      */
    898     public void testIsHeadless_notHeadless() throws DeviceNotAvailableException {
    899         mTestDevice = new TestableAndroidNativeDevice() {
    900             @Override
    901             public String getProperty(String name) throws DeviceNotAvailableException {
    902                 return null;
    903             }
    904         };
    905         assertFalse(mTestDevice.isHeadless());
    906     }
    907 
    908     /**
    909      * Unit test for {@link NativeDevice#getDeviceDate()}.
    910      */
    911     public void testGetDeviceDate() throws DeviceNotAvailableException {
    912         mTestDevice = new TestableAndroidNativeDevice() {
    913             @Override
    914             public String executeShellCommand(String name) throws DeviceNotAvailableException {
    915                 return "21692641\n";
    916             }
    917         };
    918         assertEquals(21692641000L, mTestDevice.getDeviceDate());
    919     }
    920 
    921     /**
    922      * Unit test for {@link NativeDevice#logBugreport(String, ITestLogger)}.
    923      */
    924     public void testTestLogBugreport() {
    925         final String dataName = "test";
    926         final InputStreamSource stream = new ByteArrayInputStreamSource(null);
    927         mTestDevice =
    928                 new TestableAndroidNativeDevice() {
    929                     @Override
    930                     public InputStreamSource getBugreportz() {
    931                         return stream;
    932                     }
    933 
    934                     @Override
    935                     public int getApiLevel() throws DeviceNotAvailableException {
    936                         return 24;
    937                     }
    938                 };
    939         ITestLogger listener = EasyMock.createMock(ITestLogger.class);
    940         listener.testLog(dataName, LogDataType.BUGREPORTZ, stream);
    941         EasyMock.replay(listener);
    942         assertTrue(mTestDevice.logBugreport(dataName, listener));
    943         EasyMock.verify(listener);
    944     }
    945 
    946     /**
    947      * Unit test for {@link NativeDevice#logBugreport(String, ITestLogger)}.
    948      */
    949     public void testTestLogBugreport_oldDevice() {
    950         final String dataName = "test";
    951         final InputStreamSource stream = new ByteArrayInputStreamSource(null);
    952         mTestDevice =
    953                 new TestableAndroidNativeDevice() {
    954                     @Override
    955                     public InputStreamSource getBugreportz() {
    956                         // Older device do not support bugreportz and return null
    957                         return null;
    958                     }
    959 
    960                     @Override
    961                     public InputStreamSource getBugreportInternal() {
    962                         return stream;
    963                     }
    964 
    965                     @Override
    966                     public int getApiLevel() throws DeviceNotAvailableException {
    967                         // no bugreportz support
    968                         return 23;
    969                     }
    970                 };
    971         ITestLogger listener = EasyMock.createMock(ITestLogger.class);
    972         listener.testLog(dataName, LogDataType.BUGREPORT, stream);
    973         EasyMock.replay(listener);
    974         assertTrue(mTestDevice.logBugreport(dataName, listener));
    975         EasyMock.verify(listener);
    976     }
    977 
    978     /**
    979      * Unit test for {@link NativeDevice#logBugreport(String, ITestLogger)}.
    980      */
    981     public void testTestLogBugreport_fail() {
    982         mTestDevice =
    983                 new TestableAndroidNativeDevice() {
    984                     @Override
    985                     public InputStreamSource getBugreportz() {
    986                         return null;
    987                     }
    988 
    989                     @Override
    990                     protected InputStreamSource getBugreportInternal() {
    991                         return null;
    992                     }
    993 
    994                     @Override
    995                     public int getApiLevel() throws DeviceNotAvailableException {
    996                         return 23;
    997                     }
    998                 };
    999         ITestLogger listener = EasyMock.createMock(ITestLogger.class);
   1000         EasyMock.replay(listener);
   1001         assertFalse(mTestDevice.logBugreport("test", listener));
   1002         EasyMock.verify(listener);
   1003     }
   1004 
   1005     /**
   1006      * Unit test for {@link NativeDevice#takeBugreport()}.
   1007      */
   1008     public void testTakeBugreport_apiLevelFail() {
   1009         mTestDevice = new TestableAndroidNativeDevice() {
   1010             @Override
   1011             public int getApiLevel() throws DeviceNotAvailableException {
   1012                 throw new DeviceNotAvailableException();
   1013             }
   1014         };
   1015         // If we can't check API level it should return null.
   1016         assertNull(mTestDevice.takeBugreport());
   1017     }
   1018 
   1019     /**
   1020      * Unit test for {@link NativeDevice#takeBugreport()}.
   1021      */
   1022     public void testTakeBugreport_oldDevice() throws Exception {
   1023         mTestDevice = new TestableAndroidNativeDevice() {
   1024             @Override
   1025             public int getApiLevel() throws DeviceNotAvailableException {
   1026                 return 19;
   1027             }
   1028         };
   1029         Bugreport report = mTestDevice.takeBugreport();
   1030         try {
   1031             assertNotNull(report);
   1032             // older device report a non zipped bugreport
   1033             assertFalse(report.isZipped());
   1034         } finally {
   1035             report.close();
   1036         }
   1037     }
   1038 
   1039     /**
   1040      * Unit test for {@link NativeDevice#takeBugreport()}.
   1041      */
   1042     public void testTakeBugreport() throws Exception {
   1043         mTestDevice = new TestableAndroidNativeDevice() {
   1044             @Override
   1045             public int getApiLevel() throws DeviceNotAvailableException {
   1046                 return 24;
   1047             }
   1048             @Override
   1049             protected File getBugreportzInternal() {
   1050                 try {
   1051                     return FileUtil.createTempFile("bugreportz", ".zip");
   1052                 } catch (IOException e) {
   1053                     return null;
   1054                 }
   1055             }
   1056         };
   1057         Bugreport report = mTestDevice.takeBugreport();
   1058         try {
   1059             assertNotNull(report);
   1060             assertTrue(report.isZipped());
   1061         } finally {
   1062             report.close();
   1063         }
   1064     }
   1065 
   1066     /**
   1067      * Unit test for {@link NativeDevice#getDeviceDate()}.
   1068      */
   1069     public void testGetDeviceDate_wrongformat() throws DeviceNotAvailableException {
   1070         mTestDevice = new TestableAndroidNativeDevice() {
   1071             @Override
   1072             public String executeShellCommand(String name) throws DeviceNotAvailableException {
   1073                 return "WRONG\n";
   1074             }
   1075         };
   1076         assertEquals(0, mTestDevice.getDeviceDate());
   1077     }
   1078 
   1079     public void testGetBugreport_deviceUnavail() throws Exception {
   1080         final String expectedOutput = "this is the output\r\n in two lines\r\n";
   1081         mTestDevice = new TestableAndroidNativeDevice() {
   1082             @Override
   1083             public void executeShellCommand(
   1084                     String command, IShellOutputReceiver receiver,
   1085                     long maxTimeToOutputShellResponse, TimeUnit timeUnit, int retryAttempts)
   1086                             throws DeviceNotAvailableException {
   1087                 String fakeRep = expectedOutput;
   1088                 receiver.addOutput(fakeRep.getBytes(), 0, fakeRep.getBytes().length);
   1089             }
   1090             @Override
   1091             public int getApiLevel() throws DeviceNotAvailableException {
   1092                 return 22;
   1093             }
   1094         };
   1095 
   1096         // FIXME: this isn't actually causing a DeviceNotAvailableException to be thrown
   1097         mMockRecovery.recoverDevice(EasyMock.eq(mMockStateMonitor), EasyMock.eq(false));
   1098         EasyMock.expectLastCall().andThrow(new DeviceNotAvailableException());
   1099         EasyMock.replay(mMockRecovery, mMockIDevice);
   1100         assertEquals(expectedOutput, StreamUtil.getStringFromStream(
   1101                 mTestDevice.getBugreport().createInputStream()));
   1102     }
   1103 
   1104     public void testGetBugreport_compatibility_deviceUnavail() throws Exception {
   1105         mTestDevice = new TestableAndroidNativeDevice() {
   1106             @Override
   1107             public void executeShellCommand(
   1108                     String command, IShellOutputReceiver receiver,
   1109                     long maxTimeToOutputShellResponse, TimeUnit timeUnit, int retryAttempts)
   1110                             throws DeviceNotAvailableException {
   1111                 throw new DeviceNotAvailableException();
   1112             }
   1113             @Override
   1114             public int getApiLevel() throws DeviceNotAvailableException {
   1115                 return 24;
   1116             }
   1117             @Override
   1118             public IFileEntry getFileEntry(String path) throws DeviceNotAvailableException {
   1119                 return null;
   1120             }
   1121         };
   1122         EasyMock.replay(mMockRecovery, mMockIDevice);
   1123         assertEquals(0, mTestDevice.getBugreport().size());
   1124         EasyMock.verify(mMockRecovery, mMockIDevice);
   1125     }
   1126 
   1127     public void testGetBugreport_deviceUnavail_fallback() throws Exception {
   1128         final IFileEntry fakeEntry = EasyMock.createMock(IFileEntry.class);
   1129         mTestDevice = new TestableAndroidNativeDevice() {
   1130             @Override
   1131             public void executeShellCommand(
   1132                     String command, IShellOutputReceiver receiver,
   1133                     long maxTimeToOutputShellResponse, TimeUnit timeUnit, int retryAttempts)
   1134                             throws DeviceNotAvailableException {
   1135                 throw new DeviceNotAvailableException();
   1136             }
   1137             @Override
   1138             public int getApiLevel() throws DeviceNotAvailableException {
   1139                 return 24;
   1140             }
   1141             @Override
   1142             public IFileEntry getFileEntry(String path) throws DeviceNotAvailableException {
   1143                 return fakeEntry;
   1144             }
   1145             @Override
   1146             public File pullFile(String remoteFilePath) throws DeviceNotAvailableException {
   1147                 try {
   1148                     return FileUtil.createTempFile("bugreport", ".txt");
   1149                 } catch (IOException e) {
   1150                     return null;
   1151                 }
   1152             }
   1153         };
   1154         List<IFileEntry> list = new ArrayList<>();
   1155         list.add(fakeEntry);
   1156         EasyMock.expect(fakeEntry.getChildren(false)).andReturn(list);
   1157         EasyMock.expect(fakeEntry.getName()).andReturn("bugreport-NYC-2016-08-17-10-17-00.tmp");
   1158         EasyMock.replay(fakeEntry, mMockRecovery, mMockIDevice);
   1159         InputStreamSource res = null;
   1160         try {
   1161             res = mTestDevice.getBugreport();
   1162             assertNotNull(res);
   1163             EasyMock.verify(fakeEntry, mMockRecovery, mMockIDevice);
   1164         } finally {
   1165             StreamUtil.cancel(res);
   1166         }
   1167     }
   1168 
   1169     /**
   1170      * Unit test for {@link NativeDevice#getBugreportz()}.
   1171      */
   1172     public void testGetBugreportz() throws IOException {
   1173         mTestDevice = new TestableAndroidNativeDevice() {
   1174             @Override
   1175             public void executeShellCommand(
   1176                     String command, IShellOutputReceiver receiver,
   1177                     long maxTimeToOutputShellResponse, TimeUnit timeUnit, int retryAttempts)
   1178                             throws DeviceNotAvailableException {
   1179                 String fakeRep = "OK:/data/0/com.android.shell/bugreports/bugreport1970-10-27.zip";
   1180                 receiver.addOutput(fakeRep.getBytes(), 0, fakeRep.getBytes().length);
   1181             }
   1182             @Override
   1183             public boolean doesFileExist(String destPath) throws DeviceNotAvailableException {
   1184                 return true;
   1185             }
   1186             @Override
   1187             public boolean pullFile(String remoteFilePath, File localFile)
   1188                     throws DeviceNotAvailableException {
   1189                 return true;
   1190             }
   1191             @Override
   1192             public String executeShellCommand(String command) throws DeviceNotAvailableException {
   1193                 assertEquals("rm /data/0/com.android.shell/bugreports/*", command);
   1194                 return null;
   1195             }
   1196             @Override
   1197             public int getApiLevel() throws DeviceNotAvailableException {
   1198                 return 24;
   1199             }
   1200         };
   1201         FileInputStreamSource f = null;
   1202         try {
   1203             f = (FileInputStreamSource) mTestDevice.getBugreportz();
   1204             assertNotNull(f);
   1205             assertTrue(f.createInputStream().available() == 0);
   1206         } finally {
   1207             StreamUtil.cancel(f);
   1208             if (f != null) {
   1209                 f.cleanFile();
   1210             }
   1211         }
   1212     }
   1213 
   1214     /**
   1215      * Unit test for {@link NativeDevice#getBugreportz()}.
   1216      */
   1217     public void testGetBugreportz_fails() {
   1218         mTestDevice =
   1219                 new TestableAndroidNativeDevice() {
   1220                     @Override
   1221                     public int getApiLevel() throws DeviceNotAvailableException {
   1222                         return 24;
   1223                     }
   1224 
   1225                     @Override
   1226                     protected File getBugreportzInternal() {
   1227                         return null;
   1228                     }
   1229 
   1230                     @Override
   1231                     public IFileEntry getFileEntry(String path) throws DeviceNotAvailableException {
   1232                         return null;
   1233                     }
   1234                 };
   1235         FileInputStreamSource f = null;
   1236         try {
   1237             f = (FileInputStreamSource) mTestDevice.getBugreportz();
   1238             assertNull(f);
   1239         } finally {
   1240             StreamUtil.cancel(f);
   1241             if (f != null) {
   1242                 f.cleanFile();
   1243             }
   1244         }
   1245     }
   1246 
   1247     /**
   1248      * Test that we can distinguish a newer file even with Timezone on the device.
   1249      * Seoul is GMT+9.
   1250      */
   1251     public void testIsNewer() throws Exception {
   1252         TestableAndroidNativeDevice testDevice =
   1253                 new TestableAndroidNativeDevice() {
   1254                     @Override
   1255                     public String getProperty(String name) throws DeviceNotAvailableException {
   1256                         return "Asia/Seoul";
   1257                     }
   1258 
   1259                     @Override
   1260                     public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException {
   1261                         return 0;
   1262                     }
   1263                 };
   1264         File localFile = FileUtil.createTempFile("timezonetest", ".txt");
   1265         try {
   1266             localFile.setLastModified(1470906000000l); // Thu Aug 11 09:00:00 GMT 2016
   1267             IFileEntry remoteFile = EasyMock.createMock(IFileEntry.class);
   1268             EasyMock.expect(remoteFile.getDate()).andReturn("2016-08-11");
   1269             EasyMock.expect(remoteFile.getTime()).andReturn("18:00");
   1270             EasyMock.replay(remoteFile);
   1271             assertTrue(testDevice.isNewer(localFile, remoteFile));
   1272             EasyMock.verify(remoteFile);
   1273         } finally {
   1274             FileUtil.deleteFile(localFile);
   1275         }
   1276     }
   1277 
   1278     /**
   1279      * Test that we can distinguish a newer file even with Timezone on the device.
   1280      * Seoul is GMT+9. Clock on device is inaccurate and in advance of host.
   1281      */
   1282     public void testIsNewer_timeOffset() throws Exception {
   1283         TestableAndroidNativeDevice testDevice =
   1284                 new TestableAndroidNativeDevice() {
   1285                     @Override
   1286                     public String getProperty(String name) throws DeviceNotAvailableException {
   1287                         return "Asia/Seoul";
   1288                     }
   1289 
   1290                     @Override
   1291                     public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException {
   1292                         return -15 * 60 * 1000; // Device in advance of 15m on host.
   1293                     }
   1294                 };
   1295         File localFile = FileUtil.createTempFile("timezonetest", ".txt");
   1296         try {
   1297             localFile.setLastModified(1470906000000l); // Thu, 11 Aug 2016 09:00:00 GMT
   1298             IFileEntry remoteFile = EasyMock.createMock(IFileEntry.class);
   1299             EasyMock.expect(remoteFile.getDate()).andReturn("2016-08-11");
   1300             EasyMock.expect(remoteFile.getTime()).andReturn("18:15");
   1301             EasyMock.replay(remoteFile);
   1302             // Should sync because after time offset correction, file is older.
   1303             assertTrue(testDevice.isNewer(localFile, remoteFile));
   1304             EasyMock.verify(remoteFile);
   1305         } finally {
   1306             FileUtil.deleteFile(localFile);
   1307         }
   1308     }
   1309 
   1310     /**
   1311      * Test that we can distinguish a newer file even with Timezone on the device.
   1312      * Seoul is GMT+9.
   1313      * Local file is set to 10min earlier than remoteFile.
   1314      */
   1315     public void testIsNewer_fails() throws Exception {
   1316         TestableAndroidNativeDevice testDevice =
   1317                 new TestableAndroidNativeDevice() {
   1318                     @Override
   1319                     public String getProperty(String name) throws DeviceNotAvailableException {
   1320                         return "Asia/Seoul";
   1321                     }
   1322 
   1323                     @Override
   1324                     public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException {
   1325                         return 0;
   1326                     }
   1327                 };
   1328         File localFile = FileUtil.createTempFile("timezonetest", ".txt");
   1329         try {
   1330             localFile.setLastModified(1470906000000l); // Thu, 11 Aug 2016 09:00:00 GMT
   1331             IFileEntry remoteFile = EasyMock.createMock(IFileEntry.class);
   1332             EasyMock.expect(remoteFile.getDate()).andReturn("2016-08-11");
   1333             EasyMock.expect(remoteFile.getTime()).andReturn("18:10");
   1334             EasyMock.replay(remoteFile);
   1335             assertFalse(testDevice.isNewer(localFile, remoteFile));
   1336             EasyMock.verify(remoteFile);
   1337         } finally {
   1338             FileUtil.deleteFile(localFile);
   1339         }
   1340     }
   1341 
   1342     /**
   1343      * Unit test for {@link NativeDevice#getBuildAlias()}.
   1344      */
   1345     public void testGetBuildAlias() throws DeviceNotAvailableException {
   1346         final String alias = "alias\n";
   1347         mTestDevice = new TestableAndroidNativeDevice() {
   1348             @Override
   1349             public String getProperty(String name) throws DeviceNotAvailableException {
   1350                 return alias;
   1351             }
   1352         };
   1353         assertEquals(alias, mTestDevice.getBuildAlias());
   1354     }
   1355 
   1356     /**
   1357      * Unit test for {@link NativeDevice#getBuildAlias()}.
   1358      */
   1359     public void testGetBuildAlias_null() throws DeviceNotAvailableException {
   1360         final String alias = null;
   1361         final String buildId = "alias\n";
   1362         mTestDevice = new TestableAndroidNativeDevice() {
   1363             @Override
   1364             public String getProperty(String name) throws DeviceNotAvailableException {
   1365                 return alias;
   1366             }
   1367             @Override
   1368             public String getBuildId() throws DeviceNotAvailableException {
   1369                 return buildId;
   1370             }
   1371         };
   1372         assertEquals(buildId, mTestDevice.getBuildAlias());
   1373     }
   1374 
   1375     /**
   1376      * Unit test for {@link NativeDevice#getBuildAlias()}.
   1377      */
   1378     public void testGetBuildAlias_empty() throws DeviceNotAvailableException {
   1379         final String alias = "";
   1380         final String buildId = "alias\n";
   1381         mTestDevice = new TestableAndroidNativeDevice() {
   1382             @Override
   1383             public String getProperty(String name) throws DeviceNotAvailableException {
   1384                 return alias;
   1385             }
   1386             @Override
   1387             public String getBuildId() throws DeviceNotAvailableException {
   1388                 return buildId;
   1389             }
   1390         };
   1391         assertEquals(buildId, mTestDevice.getBuildAlias());
   1392     }
   1393 
   1394     /**
   1395      * Unit test for {@link NativeDevice#getBuildId()}.
   1396      */
   1397     public void testGetBuildId() throws DeviceNotAvailableException {
   1398         final String buildId = "299865";
   1399         mTestDevice = new TestableAndroidNativeDevice() {
   1400             @Override
   1401             public String getProperty(String name) throws DeviceNotAvailableException {
   1402                 return buildId;
   1403             }
   1404         };
   1405         assertEquals(buildId, mTestDevice.getBuildId());
   1406     }
   1407 
   1408     /**
   1409      * Unit test for {@link NativeDevice#getBuildId()}.
   1410      */
   1411     public void testGetBuildId_null() throws DeviceNotAvailableException {
   1412         final String buildId = null;
   1413         mTestDevice = new TestableAndroidNativeDevice() {
   1414             @Override
   1415             public String getProperty(String name) throws DeviceNotAvailableException {
   1416                 return buildId;
   1417             }
   1418         };
   1419         assertEquals(IBuildInfo.UNKNOWN_BUILD_ID, mTestDevice.getBuildId());
   1420     }
   1421 
   1422     /**
   1423      * Unit test for {@link NativeDevice#getBuildFlavor()}.
   1424      */
   1425     public void testGetBuildFlavor() throws DeviceNotAvailableException {
   1426         final String flavor = "ham-user";
   1427         mTestDevice = new TestableAndroidNativeDevice() {
   1428             @Override
   1429             public String getProperty(String name) throws DeviceNotAvailableException {
   1430                 return flavor;
   1431             }
   1432         };
   1433         assertEquals(flavor, mTestDevice.getBuildFlavor());
   1434     }
   1435 
   1436     /**
   1437      * Unit test for {@link NativeDevice#getBuildFlavor()}.
   1438      */
   1439     public void testGetBuildFlavor_null_flavor() throws DeviceNotAvailableException {
   1440         final String productName = "prod";
   1441         final String buildType = "buildtype";
   1442         String expected = String.format("%s-%s", productName, buildType);
   1443         mTestDevice = new TestableAndroidNativeDevice() {
   1444             @Override
   1445             public String getProperty(String name) throws DeviceNotAvailableException {
   1446                 if ("ro.build.flavor".equals(name)) {
   1447                     return null;
   1448                 } else if ("ro.product.name".equals(name)) {
   1449                     return productName;
   1450                 } else if ("ro.build.type".equals(name)) {
   1451                     return buildType;
   1452                 } else {
   1453                     return null;
   1454                 }
   1455             }
   1456         };
   1457         assertEquals(expected, mTestDevice.getBuildFlavor());
   1458     }
   1459 
   1460     /**
   1461      * Unit test for {@link NativeDevice#getBuildFlavor()}.
   1462      */
   1463     public void testGetBuildFlavor_null() throws DeviceNotAvailableException {
   1464         final String productName = null;
   1465         final String buildType = "buildtype";
   1466         mTestDevice = new TestableAndroidNativeDevice() {
   1467             @Override
   1468             public String getProperty(String name) throws DeviceNotAvailableException {
   1469                 if ("ro.build.flavor".equals(name)) {
   1470                     return "";
   1471                 } else if ("ro.product.name".equals(name)) {
   1472                     return productName;
   1473                 } else if ("ro.build.type".equals(name)) {
   1474                     return buildType;
   1475                 } else {
   1476                     return null;
   1477                 }
   1478             }
   1479         };
   1480         assertNull(mTestDevice.getBuildFlavor());
   1481     }
   1482 
   1483     /**
   1484      * Unit test for {@link NativeDevice#doAdbReboot(String)}.
   1485      */
   1486     public void testDoAdbReboot_emulator() throws Exception {
   1487         final String into = "bootloader";
   1488         mMockIDevice.reboot(into);
   1489         EasyMock.expectLastCall();
   1490         EasyMock.replay(mMockIDevice);
   1491         mTestDevice.doAdbReboot(into);
   1492         EasyMock.verify(mMockIDevice);
   1493     }
   1494 
   1495     /**
   1496      * Unit test for {@link NativeDevice#doReboot()}.
   1497      */
   1498     public void testDoReboot() throws Exception {
   1499         NativeDevice testDevice = new NativeDevice(mMockIDevice,
   1500                 mMockStateMonitor, mMockDvcMonitor) {
   1501             @Override
   1502             public TestDeviceState getDeviceState() {
   1503                 return TestDeviceState.ONLINE;
   1504             }
   1505         };
   1506         mMockIDevice.reboot(null);
   1507         EasyMock.expectLastCall();
   1508         EasyMock.expect(mMockStateMonitor.waitForDeviceNotAvailable(EasyMock.anyLong()))
   1509                 .andReturn(true);
   1510         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1511         testDevice.doReboot();
   1512         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1513     }
   1514 
   1515     /**
   1516      * Unit test for {@link NativeDevice#doReboot()}.
   1517      */
   1518     public void testDoReboot_skipped() throws Exception {
   1519         NativeDevice testDevice = new NativeDevice(mMockIDevice,
   1520                 mMockStateMonitor, mMockDvcMonitor) {
   1521             @Override
   1522             public TestDeviceState getDeviceState() {
   1523                 mOptions = new TestDeviceOptions() {
   1524                     @Override
   1525                     public boolean shouldDisableReboot() {
   1526                         return true;
   1527                     }
   1528                 };
   1529                 return TestDeviceState.ONLINE;
   1530             }
   1531         };
   1532         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1533         testDevice.doReboot();
   1534         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1535     }
   1536 
   1537     /**
   1538      * Unit test for {@link NativeDevice#doReboot()}.
   1539      */
   1540     public void testDoReboot_fastboot() throws Exception {
   1541         mTestDevice = new TestableAndroidNativeDevice() {
   1542             @Override
   1543             public TestDeviceState getDeviceState() {
   1544                 return TestDeviceState.FASTBOOT;
   1545             }
   1546             @Override
   1547             public CommandResult executeFastbootCommand(String... cmdArgs)
   1548                     throws DeviceNotAvailableException, UnsupportedOperationException {
   1549                 wasCalled = true;
   1550                 return new CommandResult();
   1551             }
   1552         };
   1553         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1554         mTestDevice.doReboot();
   1555         assertTrue(mTestDevice.wasCalled);
   1556         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1557     }
   1558 
   1559     /**
   1560      * Unit test for {@link NativeDevice#unlockDevice()} already decrypted.
   1561      */
   1562     public void testUnlockDevice_skipping() throws Exception {
   1563         mTestDevice = new TestableAndroidNativeDevice() {
   1564             @Override
   1565             public boolean isEncryptionSupported() throws DeviceNotAvailableException {
   1566                 return true;
   1567             }
   1568             @Override
   1569             public boolean isDeviceEncrypted() throws DeviceNotAvailableException {
   1570                 return false;
   1571             }
   1572         };
   1573         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1574         assertTrue(mTestDevice.unlockDevice());
   1575         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1576     }
   1577 
   1578     /**
   1579      * Unit test for {@link NativeDevice#unlockDevice()}.
   1580      */
   1581     public void testUnlockDevice() throws Exception {
   1582         mTestDevice = new TestableAndroidNativeDevice() {
   1583             @Override
   1584             public boolean isEncryptionSupported() throws DeviceNotAvailableException {
   1585                 return true;
   1586             }
   1587             @Override
   1588             public boolean isDeviceEncrypted() throws DeviceNotAvailableException {
   1589                 return true;
   1590             }
   1591             @Override
   1592             public boolean enableAdbRoot() throws DeviceNotAvailableException {
   1593                 return true;
   1594             }
   1595             @Override
   1596             public String executeShellCommand(String command) throws DeviceNotAvailableException {
   1597                 return "200 checkpw -1";
   1598             }
   1599         };
   1600         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1601         assertTrue(mTestDevice.unlockDevice());
   1602         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1603     }
   1604 
   1605     /**
   1606      * Unit test for {@link NativeDevice#unlockDevice()}.
   1607      */
   1608     public void testUnlockDevice_garbageOutput() throws Exception {
   1609         mTestDevice = new TestableAndroidNativeDevice() {
   1610             @Override
   1611             public boolean isEncryptionSupported() throws DeviceNotAvailableException {
   1612                 return true;
   1613             }
   1614             @Override
   1615             public boolean isDeviceEncrypted() throws DeviceNotAvailableException {
   1616                 return true;
   1617             }
   1618             @Override
   1619             public boolean enableAdbRoot() throws DeviceNotAvailableException {
   1620                 return true;
   1621             }
   1622             @Override
   1623             public String executeShellCommand(String command) throws DeviceNotAvailableException {
   1624                 return "gdsgdgggsgdg not working";
   1625             }
   1626         };
   1627         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1628         assertFalse(mTestDevice.unlockDevice());
   1629         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1630     }
   1631 
   1632     /**
   1633      * Unit test for {@link NativeDevice#unlockDevice()}.
   1634      */
   1635     public void testUnlockDevice_emptyOutput() throws Exception {
   1636         mTestDevice = new TestableAndroidNativeDevice() {
   1637             @Override
   1638             public boolean isEncryptionSupported() throws DeviceNotAvailableException {
   1639                 return true;
   1640             }
   1641             @Override
   1642             public boolean isDeviceEncrypted() throws DeviceNotAvailableException {
   1643                 return true;
   1644             }
   1645             @Override
   1646             public boolean enableAdbRoot() throws DeviceNotAvailableException {
   1647                 return true;
   1648             }
   1649             @Override
   1650             public String executeShellCommand(String command) throws DeviceNotAvailableException {
   1651                 return "";
   1652             }
   1653         };
   1654         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1655         assertFalse(mTestDevice.unlockDevice());
   1656         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1657     }
   1658 
   1659     /**
   1660      * Unit test for {@link NativeDevice#unlockDevice()}.
   1661      */
   1662     public void testUnlockDevice_goodOutputPasswordEnteredCorrectly() throws Exception {
   1663         mTestDevice = new TestableAndroidNativeDevice() {
   1664             @Override
   1665             public boolean isEncryptionSupported() throws DeviceNotAvailableException {
   1666                 return true;
   1667             }
   1668             @Override
   1669             public boolean isDeviceEncrypted() throws DeviceNotAvailableException {
   1670                 return true;
   1671             }
   1672             @Override
   1673             public boolean enableAdbRoot() throws DeviceNotAvailableException {
   1674                 return true;
   1675             }
   1676             @Override
   1677             public String executeShellCommand(String command) throws DeviceNotAvailableException {
   1678                 return "200 encryption 0";
   1679             }
   1680         };
   1681         EasyMock.expect(mMockStateMonitor.waitForDeviceAvailable()).andReturn(mMockIDevice);
   1682         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1683         assertTrue(mTestDevice.unlockDevice());
   1684         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   1685     }
   1686 
   1687     /**
   1688      * Test {NativeDevice#parseFreeSpaceFromModernOutput(String)} with a regular df output and
   1689      * mount name of numbers.
   1690      */
   1691     public void testParseDfOutput_mountWithNumber() {
   1692         String dfOutput = "Filesystem     1K-blocks   Used Available Use% Mounted on\n" +
   1693                 "/dev/fuse       31154688 100576  31054112   1% /storage/3134-3433";
   1694         Long res = mTestDevice.parseFreeSpaceFromModernOutput(dfOutput);
   1695         assertNotNull(res);
   1696         assertEquals(31054112L, res.longValue());
   1697     }
   1698 
   1699     /**
   1700      * Test {NativeDevice#parseFreeSpaceFromModernOutput(String)} with a regular df output and
   1701      * mount name of mix of letters and numbers.
   1702      */
   1703     public void testParseDfOutput() {
   1704         String dfOutput = "Filesystem     1K-blocks   Used Available Use% Mounted on\n" +
   1705                 "/dev/fuse       31154688 100576  31054112   1% /storage/sdcard58";
   1706         Long res = mTestDevice.parseFreeSpaceFromModernOutput(dfOutput);
   1707         assertNotNull(res);
   1708         assertEquals(31054112L, res.longValue());
   1709     }
   1710 
   1711     /**
   1712      * Test {NativeDevice#parseFreeSpaceFromModernOutput(String)} with a regular df output and
   1713      * mount name with incorrect field.
   1714      */
   1715     public void testParseDfOutput_wrongMount() {
   1716         String dfOutput = "Filesystem     1K-blocks   Used Available Use% Mounted on\n" +
   1717                 "/dev/fuse       31154688 100576  31054112   1% \test\\wrongpath";
   1718         Long res = mTestDevice.parseFreeSpaceFromModernOutput(dfOutput);
   1719         assertNull(res);
   1720     }
   1721 
   1722     /**
   1723      * Test {NativeDevice#parseFreeSpaceFromModernOutput(String)} with a regular df output and
   1724      * a filesytem name with numbers in it.
   1725      */
   1726     public void testParseDfOutput_filesystemWithNumber() {
   1727         String dfOutput = "Filesystem     1K-blocks   Used Available Use% Mounted on\n" +
   1728                 "/dev/dm-1       31154688 100576  31054112   1% /";
   1729         Long res = mTestDevice.parseFreeSpaceFromModernOutput(dfOutput);
   1730         assertNotNull(res);
   1731         assertEquals(31054112L, res.longValue());
   1732     }
   1733 
   1734     /**
   1735      * Test that {@link NativeDevice#getDeviceTimeOffset(Date)} returns the proper offset forward
   1736      */
   1737     public void testGetDeviceTimeOffset() throws DeviceNotAvailableException {
   1738         mTestDevice =
   1739                 new TestableAndroidNativeDevice() {
   1740                     @Override
   1741                     public long getDeviceDate() throws DeviceNotAvailableException {
   1742                         return 1476958881000L;
   1743                     }
   1744                 };
   1745         Date date = new Date(1476958891000L);
   1746         assertEquals(10000L, mTestDevice.getDeviceTimeOffset(date));
   1747     }
   1748 
   1749     /**
   1750      * Test that {@link NativeDevice#getDeviceTimeOffset(Date)}} returns the proper offset when
   1751      * there is delay.
   1752      */
   1753     public void testGetDeviceTimeOffset_delay() throws DeviceNotAvailableException {
   1754         mTestDevice =
   1755                 new TestableAndroidNativeDevice() {
   1756                     @Override
   1757                     public long getDeviceDate() throws DeviceNotAvailableException {
   1758                         // DeviceDate is in second
   1759                         return 1476958891000L;
   1760                     }
   1761                 };
   1762         // Date takes millisecond since Epoch
   1763         Date date = new Date(1476958881000L);
   1764         assertEquals(-10000L, mTestDevice.getDeviceTimeOffset(date));
   1765     }
   1766 
   1767     /**
   1768      * Test that {@link NativeDevice#setDate(Date)} returns the proper offset when
   1769      * there is delay with api level above 24, posix format is used.
   1770      */
   1771     public void testSetDate() throws DeviceNotAvailableException {
   1772         Date date = new Date(1476958881000L);
   1773         mTestDevice =
   1774                 new TestableAndroidNativeDevice() {
   1775                     @Override
   1776                     public int getApiLevel() throws DeviceNotAvailableException {
   1777                         return 24;
   1778                     }
   1779 
   1780                     @Override
   1781                     public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException {
   1782                         // right above set threshold
   1783                         return NativeDevice.MAX_HOST_DEVICE_TIME_OFFSET + 1;
   1784                     }
   1785 
   1786                     @Override
   1787                     public String executeShellCommand(String command)
   1788                             throws DeviceNotAvailableException {
   1789                         CLog.e("%s", command);
   1790                         assertEquals("date -u 102010212016.21", command);
   1791                         return command;
   1792                     }
   1793                 };
   1794         mTestDevice.setDate(date);
   1795     }
   1796 
   1797     /**
   1798      * Test that {@link NativeDevice#setDate(Date)} returns the proper offset when
   1799      * there is delay with api level below 23, regular second format is used.
   1800      */
   1801     public void testSetDate_lowApi() throws DeviceNotAvailableException {
   1802         Date date = new Date(1476958881000L);
   1803         mTestDevice =
   1804                 new TestableAndroidNativeDevice() {
   1805                     @Override
   1806                     public int getApiLevel() throws DeviceNotAvailableException {
   1807                         return 22;
   1808                     }
   1809 
   1810                     @Override
   1811                     public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException {
   1812                         // right above set threshold
   1813                         return NativeDevice.MAX_HOST_DEVICE_TIME_OFFSET + 1;
   1814                     }
   1815 
   1816                     @Override
   1817                     public String executeShellCommand(String command)
   1818                             throws DeviceNotAvailableException {
   1819                         CLog.e("%s", command);
   1820                         assertEquals("date -u 1476958881", command);
   1821                         return command;
   1822                     }
   1823                 };
   1824         mTestDevice.setDate(date);
   1825     }
   1826 
   1827     /**
   1828      * Test that {@link NativeDevice#setDate(Date)} does not attemp to set if bellow threshold.
   1829      */
   1830     public void testSetDate_NoAction() throws DeviceNotAvailableException {
   1831         Date date = new Date(1476958881000L);
   1832         mTestDevice =
   1833                 new TestableAndroidNativeDevice() {
   1834                     @Override
   1835                     public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException {
   1836                         // right below set threshold
   1837                         return NativeDevice.MAX_HOST_DEVICE_TIME_OFFSET - 1;
   1838                     }
   1839 
   1840                     @Override
   1841                     public String executeShellCommand(String command)
   1842                             throws DeviceNotAvailableException {
   1843                         fail("Should not be called");
   1844                         return command;
   1845                     }
   1846                 };
   1847         mTestDevice.setDate(date);
   1848     }
   1849 
   1850     /**
   1851      * Test that {@link NativeDevice#getDeviceDescriptor()} returns the proper information.
   1852      */
   1853     public void testGetDeviceDescriptor() {
   1854         final String serial = "Test";
   1855         mTestDevice = new TestableAndroidNativeDevice() {
   1856             @Override
   1857             public IDevice getIDevice() {
   1858                 return new StubDevice(serial);
   1859             }
   1860         };
   1861         DeviceDescriptor desc = mTestDevice.getDeviceDescriptor();
   1862         assertTrue(desc.isStubDevice());
   1863         assertEquals(serial, desc.getSerial());
   1864         assertEquals("StubDevice", desc.getDeviceClass());
   1865     }
   1866 
   1867     /**
   1868      * Test that {@link NativeDevice#pullFile(String, File)} returns true when the pull is
   1869      * successful.
   1870      */
   1871     public void testPullFile() throws Exception {
   1872         final String fakeRemotePath = "/test/";
   1873         SyncService s = Mockito.mock(SyncService.class);
   1874         EasyMock.expect(mMockIDevice.getSyncService()).andReturn(s);
   1875         EasyMock.replay(mMockIDevice);
   1876         File tmpFile = FileUtil.createTempFile("pull", ".test");
   1877         try {
   1878             boolean res = mTestDevice.pullFile(fakeRemotePath, tmpFile);
   1879             EasyMock.verify(mMockIDevice);
   1880             Mockito.verify(s)
   1881                     .pullFile(
   1882                             Mockito.eq(fakeRemotePath),
   1883                             Mockito.eq(tmpFile.getAbsolutePath()),
   1884                             Mockito.any(ISyncProgressMonitor.class));
   1885             Mockito.verify(s).close();
   1886             assertTrue(res);
   1887         } finally {
   1888             FileUtil.deleteFile(tmpFile);
   1889         }
   1890     }
   1891 
   1892     /**
   1893      * Test that {@link NativeDevice#pullFile(String, File)} returns false when it fails to
   1894      * pull the file.
   1895      */
   1896     public void testPullFile_fails() throws Exception {
   1897         final String fakeRemotePath = "/test/";
   1898         SyncService s = Mockito.mock(SyncService.class);
   1899         EasyMock.expect(mMockIDevice.getSyncService()).andReturn(s);
   1900         EasyMock.replay(mMockIDevice);
   1901         File tmpFile = FileUtil.createTempFile("pull", ".test");
   1902         doThrow(new SyncException(SyncError.CANCELED))
   1903                 .when(s)
   1904                 .pullFile(
   1905                         Mockito.eq(fakeRemotePath),
   1906                         Mockito.eq(tmpFile.getAbsolutePath()),
   1907                         Mockito.any(ISyncProgressMonitor.class));
   1908         try {
   1909             boolean res = mTestDevice.pullFile(fakeRemotePath, tmpFile);
   1910             EasyMock.verify(mMockIDevice);
   1911             Mockito.verify(s)
   1912                     .pullFile(
   1913                             Mockito.eq(fakeRemotePath),
   1914                             Mockito.eq(tmpFile.getAbsolutePath()),
   1915                             Mockito.any(ISyncProgressMonitor.class));
   1916             Mockito.verify(s).close();
   1917             assertFalse(res);
   1918         } finally {
   1919             FileUtil.deleteFile(tmpFile);
   1920         }
   1921     }
   1922 
   1923     /**
   1924      * Test that {@link NativeDevice#pullFile(String)} returns a file when succeed pulling the
   1925      * file.
   1926      */
   1927     public void testPullFile_returnFileSuccess() throws Exception {
   1928         final String fakeRemotePath = "/test/";
   1929         mTestDevice = new TestableAndroidNativeDevice() {
   1930             @Override
   1931             public boolean pullFile(String remoteFilePath, File localFile)
   1932                     throws DeviceNotAvailableException {
   1933                 return true;
   1934             }
   1935         };
   1936         File res = mTestDevice.pullFile(fakeRemotePath);
   1937         try {
   1938             assertNotNull(res);
   1939         } finally {
   1940             FileUtil.deleteFile(res);
   1941         }
   1942     }
   1943 
   1944     /**
   1945      * Test that {@link NativeDevice#pullFile(String)} returns null when failed to pull the file.
   1946      */
   1947     public void testPullFile_returnNull() throws Exception {
   1948         final String fakeRemotePath = "/test/";
   1949         mTestDevice = new TestableAndroidNativeDevice() {
   1950             @Override
   1951             public boolean pullFile(String remoteFilePath, File localFile)
   1952                     throws DeviceNotAvailableException {
   1953                 return false;
   1954             }
   1955         };
   1956         File res = mTestDevice.pullFile(fakeRemotePath);
   1957         try {
   1958             assertNull(res);
   1959         } finally {
   1960             FileUtil.deleteFile(res);
   1961         }
   1962     }
   1963 
   1964     /**
   1965      * Test that {@link NativeDevice#pullFileContents(String)} returns a string when succeed pulling
   1966      * the file.
   1967      */
   1968     public void testPullFileContents_returnFileSuccess() throws Exception {
   1969         final String fakeRemotePath = "/test/";
   1970         mTestDevice = new TestableAndroidNativeDevice() {
   1971             @Override
   1972             public boolean pullFile(String remoteFilePath, File localFile)
   1973                     throws DeviceNotAvailableException {
   1974                 return true;
   1975             }
   1976         };
   1977         String res = mTestDevice.pullFileContents(fakeRemotePath);
   1978         assertNotNull(res);
   1979     }
   1980 
   1981     /**
   1982      * Test that {@link NativeDevice#pullFileContents(String)} returns null when failed to pull the
   1983      * file.
   1984      */
   1985     public void testPullFileContents_returnNull() throws Exception {
   1986         final String fakeRemotePath = "/test/";
   1987         mTestDevice = new TestableAndroidNativeDevice() {
   1988             @Override
   1989             public boolean pullFile(String remoteFilePath, File localFile)
   1990                     throws DeviceNotAvailableException {
   1991                 return false;
   1992             }
   1993         };
   1994         String res = mTestDevice.pullFileContents(fakeRemotePath);
   1995         assertNull(res);
   1996     }
   1997 
   1998     /**
   1999      * Test that {@link NativeDevice#pushFile(File, String)} returns true when the push is
   2000      * successful.
   2001      */
   2002     public void testPushFile() throws Exception {
   2003         final String fakeRemotePath = "/test/";
   2004         SyncService s = Mockito.mock(SyncService.class);
   2005         EasyMock.expect(mMockIDevice.getSyncService()).andReturn(s);
   2006         EasyMock.replay(mMockIDevice);
   2007         File tmpFile = FileUtil.createTempFile("push", ".test");
   2008         try {
   2009             boolean res = mTestDevice.pushFile(tmpFile, fakeRemotePath);
   2010             EasyMock.verify(mMockIDevice);
   2011             Mockito.verify(s)
   2012                     .pushFile(
   2013                             Mockito.eq(tmpFile.getAbsolutePath()),
   2014                             Mockito.eq(fakeRemotePath),
   2015                             Mockito.any(ISyncProgressMonitor.class));
   2016             Mockito.verify(s).close();
   2017             assertTrue(res);
   2018         } finally {
   2019             FileUtil.deleteFile(tmpFile);
   2020         }
   2021     }
   2022 
   2023     /**
   2024      * Test that {@link NativeDevice#pushFile(File, String)} returns false when the push is
   2025      * unsuccessful.
   2026      */
   2027     public void testPushFile_fails() throws Exception {
   2028         final String fakeRemotePath = "/test/";
   2029         SyncService s = Mockito.mock(SyncService.class);
   2030         EasyMock.expect(mMockIDevice.getSyncService()).andReturn(s);
   2031         EasyMock.replay(mMockIDevice);
   2032         File tmpFile = FileUtil.createTempFile("push", ".test");
   2033         doThrow(new SyncException(SyncError.CANCELED))
   2034                 .when(s)
   2035                 .pushFile(
   2036                         Mockito.eq(tmpFile.getAbsolutePath()),
   2037                         Mockito.eq(fakeRemotePath),
   2038                         Mockito.any(ISyncProgressMonitor.class));
   2039         try {
   2040             boolean res = mTestDevice.pushFile(tmpFile, fakeRemotePath);
   2041             EasyMock.verify(mMockIDevice);
   2042             Mockito.verify(s)
   2043                     .pushFile(
   2044                             Mockito.eq(tmpFile.getAbsolutePath()),
   2045                             Mockito.eq(fakeRemotePath),
   2046                             Mockito.any(ISyncProgressMonitor.class));
   2047             Mockito.verify(s).close();
   2048             assertFalse(res);
   2049         } finally {
   2050             FileUtil.deleteFile(tmpFile);
   2051         }
   2052     }
   2053 
   2054     /**
   2055      * Test validating valid MAC addresses
   2056      */
   2057     public void testIsMacAddress() {
   2058         assertTrue(mTestDevice.isMacAddress("00:00:00:00:00:00"));
   2059         assertTrue(mTestDevice.isMacAddress("00:15:E9:2B:99:3C"));
   2060         assertTrue(mTestDevice.isMacAddress("FF:FF:FF:FF:FF:FF"));
   2061         assertTrue(mTestDevice.isMacAddress("58:a2:b5:7d:49:24"));
   2062     }
   2063 
   2064     /**
   2065      * Test validating invalid MAC addresses
   2066      */
   2067     public void testIsMacAddress_invalidInput() {
   2068         assertFalse(mTestDevice.isMacAddress(""));
   2069         assertFalse(mTestDevice.isMacAddress("00-15-E9-2B-99-3C")); // Invalid delimiter
   2070     }
   2071 
   2072     /**
   2073      * Test querying a device MAC address
   2074      */
   2075     public void testGetMacAddress() throws Exception {
   2076         String address = "58:a2:b5:7d:49:24";
   2077         IDevice device = new StubDevice(MOCK_DEVICE_SERIAL) {
   2078             @Override
   2079             public void executeShellCommand(String command, IShellOutputReceiver receiver)
   2080                     throws TimeoutException, AdbCommandRejectedException,
   2081                     ShellCommandUnresponsiveException, IOException {
   2082                 receiver.addOutput(address.getBytes(), 0, address.length());
   2083             }
   2084         };
   2085         mMockIDevice.executeShellCommand(EasyMock.anyObject(), EasyMock.anyObject());
   2086         EasyMock.expectLastCall().andDelegateTo(device).anyTimes();
   2087         EasyMock.replay(mMockIDevice);
   2088         assertEquals(address, mTestDevice.getMacAddress());
   2089         EasyMock.verify(mMockIDevice);
   2090     }
   2091 
   2092     /**
   2093      * Test querying a device MAC address when the device is in fastboot
   2094      */
   2095     public void testGetMacAddress_fastboot() throws Exception {
   2096         mTestDevice.setDeviceState(TestDeviceState.FASTBOOT);
   2097         // Will fail if executeShellCommand is called. Which it should not.
   2098         assertNull(mTestDevice.getMacAddress());
   2099     }
   2100 
   2101     /**
   2102      * Test querying a device MAC address but failing to do so
   2103      */
   2104     public void testGetMacAddress_failure() throws Exception {
   2105         IDevice device = new StubDevice(MOCK_DEVICE_SERIAL) {
   2106             @Override
   2107             public void executeShellCommand(String command, IShellOutputReceiver receiver)
   2108                     throws TimeoutException, AdbCommandRejectedException,
   2109                     ShellCommandUnresponsiveException, IOException {
   2110                 throw new IOException();
   2111             }
   2112         };
   2113         mMockIDevice.executeShellCommand(EasyMock.anyObject(), EasyMock.anyObject());
   2114         EasyMock.expectLastCall().andDelegateTo(device).anyTimes();
   2115         EasyMock.replay(mMockIDevice);
   2116         assertNull(mTestDevice.getMacAddress());
   2117         EasyMock.verify(mMockIDevice);
   2118     }
   2119 
   2120     /**
   2121      * Test querying a device MAC address for a stub device
   2122      */
   2123     public void testGetMacAddress_stubDevice() throws Exception {
   2124         String address = "58:a2:b5:7d:49:24";
   2125         IDevice device = new StubDevice(MOCK_DEVICE_SERIAL) {
   2126             @Override
   2127             public void executeShellCommand(String command, IShellOutputReceiver receiver)
   2128                     throws TimeoutException, AdbCommandRejectedException,
   2129                     ShellCommandUnresponsiveException, IOException {
   2130                 receiver.addOutput(address.getBytes(), 0, address.length());
   2131             }
   2132         };
   2133         mTestDevice.setIDevice(device);
   2134         assertNull(mTestDevice.getMacAddress());
   2135     }
   2136 
   2137     /** Test that a non online device return null for sim state. */
   2138     public void testGetSimState_unavailableDevice() {
   2139         mMockIDevice = EasyMock.createMock(IDevice.class);
   2140         EasyMock.expect(mMockIDevice.getState()).andReturn(DeviceState.UNAUTHORIZED);
   2141         EasyMock.expect(mMockIDevice.getSerialNumber()).andReturn("serial");
   2142         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   2143         assertNull(mTestDevice.getSimState());
   2144         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   2145     }
   2146 
   2147     /** Test that a non online device return null for sim operator. */
   2148     public void testGetSimOperator_unavailableDevice() {
   2149         mMockIDevice = EasyMock.createMock(IDevice.class);
   2150         EasyMock.expect(mMockIDevice.getState()).andReturn(DeviceState.UNAUTHORIZED);
   2151         EasyMock.expect(mMockIDevice.getSerialNumber()).andReturn("serial");
   2152         EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   2153         assertNull(mTestDevice.getSimOperator());
   2154         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
   2155     }
   2156 
   2157     /**
   2158      * Test that when a {@link NativeDevice#getLogcatSince(long)} is requested a matching logcat
   2159      * command is generated.
   2160      */
   2161     public void testGetLogcatSince() throws Exception {
   2162         long date = 1512990942000L; // 2017-12-11 03:15:42.015
   2163         EasyMock.expect(mMockIDevice.getState()).andReturn(DeviceState.ONLINE);
   2164         SettableFuture<String> value = SettableFuture.create();
   2165         value.set("23");
   2166         EasyMock.expect(mMockIDevice.getSystemProperty("ro.build.version.sdk")).andReturn(value);
   2167         mMockIDevice.executeShellCommand(
   2168                 EasyMock.eq("logcat -v threadtime -t '12-11 03:15:42.015'"), EasyMock.anyObject());
   2169         EasyMock.replay(mMockIDevice);
   2170         mTestDevice.getLogcatSince(date);
   2171         EasyMock.verify(mMockIDevice);
   2172     }
   2173 
   2174     public void testGetProductVariant() throws Exception {
   2175         EasyMock.expect(mMockIDevice.getProperty(DeviceProperties.VARIANT)).andReturn("variant");
   2176 
   2177         EasyMock.replay(mMockIDevice);
   2178         assertEquals("variant", mTestDevice.getProductVariant());
   2179         EasyMock.verify(mMockIDevice);
   2180     }
   2181 
   2182     public void testGetProductVariant_legacy() throws Exception {
   2183         TestableAndroidNativeDevice testDevice =
   2184                 new TestableAndroidNativeDevice() {
   2185                     @Override
   2186                     protected String internalGetProperty(
   2187                             String propName, String fastbootVar, String description)
   2188                             throws DeviceNotAvailableException, UnsupportedOperationException {
   2189                         if (DeviceProperties.VARIANT_LEGACY.equals(propName)) {
   2190                             return "legacy";
   2191                         }
   2192                         return null;
   2193                     }
   2194                 };
   2195 
   2196         assertEquals("legacy", testDevice.getProductVariant());
   2197     }
   2198 
   2199     /** Test when {@link NativeDevice#executeShellV2Command(String)} returns a success. */
   2200     public void testExecuteShellV2Command() throws Exception {
   2201         CommandResult res = new CommandResult();
   2202         res.setStatus(CommandStatus.SUCCESS);
   2203         EasyMock.expect(
   2204                         mMockRunUtil.runTimedCmd(
   2205                                 100, "adb", "-s", "serial", "shell", "some", "command"))
   2206                 .andReturn(res);
   2207         EasyMock.replay(mMockRunUtil, mMockIDevice);
   2208         assertNotNull(mTestDevice.executeShellV2Command("some command"));
   2209         EasyMock.verify(mMockRunUtil, mMockIDevice);
   2210     }
   2211 
   2212     /**
   2213      * Test when {@link NativeDevice#executeShellV2Command(String, long, TimeUnit, int)} fails and
   2214      * repeat because of a timeout.
   2215      */
   2216     public void testExecuteShellV2Command_timeout() throws Exception {
   2217         CommandResult res = new CommandResult();
   2218         res.setStatus(CommandStatus.TIMED_OUT);
   2219         res.setStderr("timed out");
   2220         EasyMock.expect(
   2221                         mMockRunUtil.runTimedCmd(
   2222                                 200L, "adb", "-s", "serial", "shell", "some", "command"))
   2223                 .andReturn(res)
   2224                 .times(2);
   2225         EasyMock.replay(mMockRunUtil, mMockIDevice);
   2226         try {
   2227             mTestDevice.executeShellV2Command("some command", 200L, TimeUnit.MILLISECONDS, 1);
   2228             fail("Should have thrown an exception.");
   2229         } catch (DeviceUnresponsiveException e) {
   2230             // expected
   2231         }
   2232         EasyMock.verify(mMockRunUtil, mMockIDevice);
   2233     }
   2234 
   2235     /**
   2236      * Test when {@link NativeDevice#executeShellV2Command(String, long, TimeUnit, int)} fails and
   2237      * output.
   2238      */
   2239     public void testExecuteShellV2Command_fail() throws Exception {
   2240         CommandResult res = new CommandResult();
   2241         res.setStatus(CommandStatus.FAILED);
   2242         res.setStderr("timed out");
   2243         EasyMock.expect(
   2244                         mMockRunUtil.runTimedCmd(
   2245                                 200L, "adb", "-s", "serial", "shell", "some", "command"))
   2246                 .andReturn(res)
   2247                 .times(1);
   2248         EasyMock.replay(mMockRunUtil, mMockIDevice);
   2249         CommandResult result =
   2250                 mTestDevice.executeShellV2Command("some command", 200L, TimeUnit.MILLISECONDS, 1);
   2251         assertNotNull(result);
   2252         // The final result is what RunUtil returned, so it contains full status information.
   2253         assertSame(res, result);
   2254         EasyMock.verify(mMockRunUtil, mMockIDevice);
   2255     }
   2256 }
   2257