| # Lint as: python2, python3 | 
 | # pylint: disable=g-direct-third-party-import | 
 | # Copyright 2015 The Bazel Authors. All rights reserved. | 
 | # | 
 | # Licensed under the Apache License, Version 2.0 (the "License"); | 
 | # you may not use this file except in compliance with the License. | 
 | # You may obtain a copy of the License at | 
 | # | 
 | #    http://www.apache.org/licenses/LICENSE-2.0 | 
 | # | 
 | # Unless required by applicable law or agreed to in writing, software | 
 | # distributed under the License is distributed on an "AS IS" BASIS, | 
 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | # See the License for the specific language governing permissions and | 
 | # limitations under the License. | 
 |  | 
 | """Unit tests for stubify_incremental_install.""" | 
 |  | 
 | from __future__ import absolute_import | 
 | from __future__ import division | 
 | from __future__ import print_function | 
 |  | 
 | import os | 
 | import unittest | 
 | import zipfile | 
 |  | 
 | # Do not edit this line. Copybara replaces it with PY2 migration helper. | 
 | import six | 
 |  | 
 | if six.PY3: | 
 |     from unittest import mock | 
 | else: | 
 |     import mock | 
 |  | 
 | from tools.android import incremental_install | 
 |  | 
 |  | 
 | class MockAdb(object): | 
 |   """Mocks the Android ADB binary.""" | 
 |  | 
 |   def __init__(self): | 
 |     # Map of file name -> contents. | 
 |     self.files = {} | 
 |     self.split_apks = set() | 
 |     self._error = None | 
 |     self.package_timestamp = None | 
 |     self._last_package_timestamp = 1 | 
 |     self.shell_cmdlns = [] | 
 |     self.abi = "armeabi-v7a" | 
 |  | 
 |   def Exec(self, args): | 
 |     if self._error: | 
 |       error_info, arg = self._error  # pylint: disable=unpacking-non-sequence | 
 |       if not arg or arg in args: | 
 |         return self._CreatePopenMock(*error_info) | 
 |  | 
 |     returncode = 0 | 
 |     stdout = "" | 
 |     stderr = "" | 
 |     cmd = args[1] | 
 |     if cmd == "push": | 
 |       # "/test/adb push local remote" | 
 |       with open(args[2], "rb") as f: | 
 |         content = f.read().decode("utf-8") | 
 |       self.files[args[3]] = content | 
 |     elif cmd == "pull": | 
 |       # "/test/adb pull remote local" | 
 |       remote = args[2] | 
 |       local = args[3] | 
 |       content = self.files.get(remote) | 
 |       if content is not None: | 
 |         with open(local, "wb") as f: | 
 |           f.write(six.ensure_binary(content, "utf-8")) | 
 |       else: | 
 |         returncode = 1 | 
 |         stderr = "remote object '%s' does not exist\n" % remote | 
 |     elif cmd == "install": | 
 |       self.package_timestamp = self._last_package_timestamp | 
 |       self._last_package_timestamp += 1 | 
 |       return self._CreatePopenMock(0, "Success", "") | 
 |     elif cmd == "install-multiple": | 
 |       if args[3] == "-p": | 
 |         with open(args[5], "rb") as f: | 
 |           content = f.read().decode("utf-8") | 
 |         self.split_apks.add(content) | 
 |       else: | 
 |         self.package_timestamp = self._last_package_timestamp | 
 |         self._last_package_timestamp += 1 | 
 |       return self._CreatePopenMock(0, "Success", "") | 
 |     elif cmd == "uninstall": | 
 |       self._CreatePopenMock(0, "Success", "") | 
 |       self.split_apks = set() | 
 |       self.package_timestamp = None | 
 |     elif cmd == "shell": | 
 |       # "/test/adb shell ..." | 
 |       # mkdir, rm, am (application manager), or monkey | 
 |       shell_cmdln = args[2] | 
 |       self.shell_cmdlns.append(shell_cmdln) | 
 |       if shell_cmdln.startswith(("mkdir", "am", "monkey", "input")): | 
 |         pass | 
 |       elif six.ensure_str(shell_cmdln).startswith("dumpsys package "): | 
 |         if self.package_timestamp is not None: | 
 |           timestamp = "firstInstallTime=%s" % self.package_timestamp | 
 |         else: | 
 |           timestamp = "" | 
 |         return self._CreatePopenMock(0, timestamp, "") | 
 |       elif six.ensure_str(shell_cmdln).startswith("rm"): | 
 |         file_path = shell_cmdln.split()[2] | 
 |         self.files.pop(file_path, None) | 
 |       elif six.ensure_str(shell_cmdln).startswith("getprop ro.product.cpu.abi"): | 
 |         return self._CreatePopenMock(0, self.abi, "") | 
 |       else: | 
 |         raise Exception("Unknown shell command line: %s" % shell_cmdln) | 
 |     # Return a mock subprocess.Popen object | 
 |     return self._CreatePopenMock(returncode, stdout, stderr) | 
 |  | 
 |   def _CreatePopenMock(self, returncode, stdout, stderr): | 
 |     return mock.Mock( | 
 |         returncode=returncode, communicate=lambda: (stdout, stderr)) | 
 |  | 
 |   def SetError(self, returncode, stdout, stderr, for_arg=None): | 
 |     self._error = ((returncode, stdout, stderr), for_arg) | 
 |  | 
 |   def SetAbi(self, abi): | 
 |     self.abi = abi | 
 |  | 
 |  | 
 | class IncrementalInstallTest(unittest.TestCase): | 
 |   """Unit tests for incremental install.""" | 
 |  | 
 |   _DEXMANIFEST = "dexmanifest.txt" | 
 |   _ADB_PATH = "/test/adb" | 
 |   _OUTPUT_MARKER = "full_deploy_marker" | 
 |   _APK = "myapp_incremental.apk" | 
 |   _RESOURCE_APK = "incremental.ap_" | 
 |   _STUB_DATAFILE = "stub_application_data.txt" | 
 |   _OLD_APP_PACKGE = "old.app.package" | 
 |   _APP_PACKAGE = "new.app.package" | 
 |   _EXEC_ROOT = "." | 
 |  | 
 |   def setUp(self): | 
 |     os.chdir(os.environ["TEST_TMPDIR"]) | 
 |  | 
 |     self._mock_adb = MockAdb() | 
 |  | 
 |     # Write the stub datafile which contains the package name of the app. | 
 |     with open(self._STUB_DATAFILE, "wb") as f: | 
 |       f.write(("\n".join([self._OLD_APP_PACKGE, self._APP_PACKAGE])) | 
 |               .encode("utf-8")) | 
 |  | 
 |     # Write the local resource apk file. | 
 |     with open(self._RESOURCE_APK, "wb") as f: | 
 |       f.write(b"resource apk") | 
 |  | 
 |     # Mock out subprocess.Popen to use our mock adb. | 
 |     self._popen_patch = mock.patch.object(incremental_install, "subprocess") | 
 |     self._popen = self._popen_patch.start().Popen | 
 |     self._popen.side_effect = lambda args, **kwargs: self._mock_adb.Exec(args) | 
 |  | 
 |   def tearDown(self): | 
 |     self._popen_patch.stop() | 
 |  | 
 |   def _CreateZip(self, name="zip1", *files): | 
 |     if not files: | 
 |       files = [("zp1", "content1"), ("zp2", "content2")] | 
 |     with zipfile.ZipFile(name, "w") as z: | 
 |       for f, content in files: | 
 |         z.writestr(f, content) | 
 |  | 
 |   def _CreateLocalManifest(self, *lines): | 
 |     content = "\n".join(lines) | 
 |     with open(self._DEXMANIFEST, "wb") as f: | 
 |       f.write(content.encode("utf-8")) | 
 |     return content | 
 |  | 
 |   def _CreateRemoteManifest(self, *lines): | 
 |     self._PutDeviceFile("dex/manifest", "\n".join(lines)) | 
 |  | 
 |   def _GetDeviceAppPath(self, f): | 
 |     return os.path.join( | 
 |         incremental_install.DEVICE_DIRECTORY, self._APP_PACKAGE, f) | 
 |  | 
 |   def _GetDeviceFile(self, f): | 
 |     return self._mock_adb.files[self._GetDeviceAppPath(f)] | 
 |  | 
 |   def _PutDeviceFile(self, f, content): | 
 |     self._mock_adb.files[self._GetDeviceAppPath(f)] = content | 
 |  | 
 |   def _DeleteDeviceFile(self, f): | 
 |     self._mock_adb.files.pop(self._GetDeviceAppPath(f), None) | 
 |  | 
 |   def _CallIncrementalInstall(self, incremental, native_libs=None, | 
 |                               split_main_apk=None, split_apks=None, | 
 |                               start_type="no"): | 
 |     if split_main_apk: | 
 |       apk = split_main_apk | 
 |     elif incremental: | 
 |       apk = None | 
 |     else: | 
 |       apk = self._APK | 
 |  | 
 |     incremental_install.IncrementalInstall( | 
 |         adb_path=self._ADB_PATH, | 
 |         execroot=self._EXEC_ROOT, | 
 |         stub_datafile=self._STUB_DATAFILE, | 
 |         dexmanifest=self._DEXMANIFEST, | 
 |         apk=apk, | 
 |         resource_apk=self._RESOURCE_APK, | 
 |         split_main_apk=split_main_apk, | 
 |         split_apks=split_apks, | 
 |         native_libs=native_libs, | 
 |         output_marker=self._OUTPUT_MARKER, | 
 |         adb_jobs=1, | 
 |         start_type=start_type, | 
 |         user_home_dir="/home/root") | 
 |  | 
 |   def testUploadToPristineDevice(self): | 
 |     self._CreateZip() | 
 |  | 
 |     with open("dex1", "wb") as f: | 
 |       f.write(b"content3") | 
 |  | 
 |     manifest = self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 0", | 
 |         "dex1 - ip3 0") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=False) | 
 |  | 
 |     resources_checksum_path = self._GetDeviceAppPath("resources_checksum") | 
 |     self.assertTrue(resources_checksum_path in self._mock_adb.files) | 
 |     self.assertEqual(manifest, self._GetDeviceFile("dex/manifest")) | 
 |     self.assertEqual("content1", self._GetDeviceFile("dex/ip1")) | 
 |     self.assertEqual("content2", self._GetDeviceFile("dex/ip2")) | 
 |     self.assertEqual("content3", self._GetDeviceFile("dex/ip3")) | 
 |     self.assertEqual("resource apk", self._GetDeviceFile("resources.ap_")) | 
 |  | 
 |   def testSplitInstallToPristineDevice(self): | 
 |     with open("split1", "wb") as f: | 
 |       f.write(b"split_content1") | 
 |  | 
 |     with open("main", "wb") as f: | 
 |       f.write(b"main_Content") | 
 |  | 
 |     self._CallIncrementalInstall( | 
 |         incremental=False, split_main_apk="main", split_apks=["split1"]) | 
 |     self.assertEqual(set(["split_content1"]), self._mock_adb.split_apks) | 
 |  | 
 |   def testSplitInstallUnchanged(self): | 
 |     with open("split1", "wb") as f: | 
 |       f.write(b"split_content1") | 
 |  | 
 |     with open("main", "wb") as f: | 
 |       f.write(b"main_Content") | 
 |  | 
 |     self._CallIncrementalInstall( | 
 |         incremental=False, split_main_apk="main", split_apks=["split1"]) | 
 |     self.assertEqual(set(["split_content1"]), self._mock_adb.split_apks) | 
 |     self._mock_adb.split_apks = set() | 
 |     self._CallIncrementalInstall( | 
 |         incremental=False, split_main_apk="main", split_apks=["split1"]) | 
 |     self.assertEqual(set([]), self._mock_adb.split_apks) | 
 |  | 
 |   def testSplitInstallChanges(self): | 
 |     with open("split1", "wb") as f: | 
 |       f.write(b"split_content1") | 
 |  | 
 |     with open("main", "wb") as f: | 
 |       f.write(b"main_Content") | 
 |  | 
 |     self._CallIncrementalInstall( | 
 |         incremental=False, split_main_apk="main", split_apks=["split1"]) | 
 |     self.assertEqual(set(["split_content1"]), self._mock_adb.split_apks) | 
 |  | 
 |     with open("split1", "wb") as f: | 
 |       f.write(b"split_content2") | 
 |     self._mock_adb.split_apks = set() | 
 |     self._CallIncrementalInstall( | 
 |         incremental=False, split_main_apk="main", split_apks=["split1"]) | 
 |     self.assertEqual(set(["split_content2"]), self._mock_adb.split_apks) | 
 |  | 
 |   def testMissingNativeManifestWithIncrementalInstall(self): | 
 |     self._CreateZip() | 
 |     with open("liba.so", "wb") as f: | 
 |       f.write(b"liba_1") | 
 |  | 
 |     # Upload a library to the device. | 
 |     native_libs = ["armeabi-v7a:liba.so"] | 
 |     self._CallIncrementalInstall(incremental=False, native_libs=native_libs) | 
 |     self.assertEqual("liba_1", self._GetDeviceFile("native/liba.so")) | 
 |  | 
 |     # Delete the manifest, overwrite the library and check that even an | 
 |     # incremental install straightens things out. | 
 |     self._PutDeviceFile("native/liba.so", "GARBAGE") | 
 |     self._CallIncrementalInstall(incremental=False, native_libs=native_libs) | 
 |     self.assertEqual("liba_1", self._GetDeviceFile("native/liba.so")) | 
 |  | 
 |   def testNonIncrementalInstallOverwritesNativeLibs(self): | 
 |     self._CreateZip() | 
 |     with open("liba.so", "wb") as f: | 
 |       f.write(b"liba_1") | 
 |  | 
 |     # Upload a library to the device. | 
 |     native_libs = ["armeabi-v7a:liba.so"] | 
 |     self._CallIncrementalInstall(incremental=False, native_libs=native_libs) | 
 |     self.assertEqual("liba_1", self._GetDeviceFile("native/liba.so")) | 
 |  | 
 |     # Change a library on the device. Incremental install should not replace the | 
 |     # changed file, because it only checks the manifest. | 
 |     self._PutDeviceFile("native/liba.so", "GARBAGE") | 
 |     self._CallIncrementalInstall(incremental=True, native_libs=native_libs) | 
 |     self.assertEqual("GARBAGE", self._GetDeviceFile("native/liba.so")) | 
 |  | 
 |     # However, a full install should overwrite it. | 
 |     self._CallIncrementalInstall(incremental=False, native_libs=native_libs) | 
 |     self.assertEqual("liba_1", self._GetDeviceFile("native/liba.so")) | 
 |  | 
 |   def testNativeAbiCompatibility(self): | 
 |     self._CreateZip() | 
 |     with open("liba.so", "wb") as f: | 
 |       f.write(b"liba") | 
 |  | 
 |     native_libs = ["armeabi:liba.so"] | 
 |     self._mock_adb.SetAbi("arm64-v8a") | 
 |     self._CallIncrementalInstall(incremental=False, native_libs=native_libs) | 
 |     self.assertEqual("liba", self._GetDeviceFile("native/liba.so")) | 
 |  | 
 |   def testUploadNativeLibs(self): | 
 |     self._CreateZip() | 
 |     with open("liba.so", "wb") as f: | 
 |       f.write(b"liba_1") | 
 |     with open("libb.so", "wb") as f: | 
 |       f.write(b"libb_1") | 
 |  | 
 |     native_libs = ["armeabi-v7a:liba.so", "armeabi-v7a:libb.so"] | 
 |     self._CallIncrementalInstall(incremental=False, native_libs=native_libs) | 
 |     self.assertEqual("liba_1", self._GetDeviceFile("native/liba.so")) | 
 |     self.assertEqual("libb_1", self._GetDeviceFile("native/libb.so")) | 
 |  | 
 |     # Change a library | 
 |     with open("libb.so", "wb") as f: | 
 |       f.write(b"libb_2") | 
 |     self._CallIncrementalInstall(incremental=True, native_libs=native_libs) | 
 |     self.assertEqual("libb_2", self._GetDeviceFile("native/libb.so")) | 
 |  | 
 |     # Delete a library | 
 |     self._CallIncrementalInstall( | 
 |         incremental=True, native_libs=["armeabi-v7a:liba.so"]) | 
 |     self.assertFalse( | 
 |         self._GetDeviceAppPath("native/libb.so") in self._mock_adb.files) | 
 |  | 
 |     # Add the deleted library back | 
 |     self._CallIncrementalInstall(incremental=True, native_libs=native_libs) | 
 |     self.assertEqual("libb_2", self._GetDeviceFile("native/libb.so")) | 
 |  | 
 |   def testUploadWithOneChangedFile(self): | 
 |     # Existing manifest from a previous install. | 
 |     self._CreateRemoteManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 1") | 
 |  | 
 |     # Existing files from a previous install. | 
 |     self._PutDeviceFile("dex/ip1", "old content1") | 
 |     self._PutDeviceFile("dex/ip2", "old content2") | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateZip() | 
 |  | 
 |     # Updated dex manifest. | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 2") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=True) | 
 |  | 
 |     # This is a bit of a dishonest test: the local content for "ip1" is | 
 |     # "content1" and the remote content for it is "old content1", but | 
 |     # the checksums for that file are the same in the local and remote manifest. | 
 |     # We just want to make sure that only one file was updated, so to | 
 |     # distinguish that we force the local and remote content to be different but | 
 |     # keep the checksum the same. | 
 |     self.assertEqual("old content1", self._GetDeviceFile("dex/ip1")) | 
 |     self.assertEqual("content2", self._GetDeviceFile("dex/ip2")) | 
 |  | 
 |   def testFullUploadWithOneChangedFile(self): | 
 |  | 
 |     # Existing manifest from a previous install. | 
 |     self._CreateRemoteManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 1") | 
 |  | 
 |     self._PutDeviceFile("dex/ip1", "old content1") | 
 |     self._PutDeviceFile("dex/ip2", "old content2") | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateZip() | 
 |  | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 2") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=False) | 
 |  | 
 |     # Even though the checksums for ip1 were the same, the file still got | 
 |     # updated. This is a bit of a dishonest test because the local and remote | 
 |     # content for ip1 were different, but their checksums were the same. | 
 |     self.assertEqual("content1", self._GetDeviceFile("dex/ip1")) | 
 |     self.assertEqual("content2", self._GetDeviceFile("dex/ip2")) | 
 |  | 
 |   def testUploadWithNewFile(self): | 
 |  | 
 |     self._CreateRemoteManifest("zip1 zp1 ip1 0") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 1") | 
 |  | 
 |     self._CreateZip() | 
 |  | 
 |     self._CallIncrementalInstall(incremental=True) | 
 |  | 
 |     self.assertEqual("content1", self._GetDeviceFile("dex/ip1")) | 
 |     self.assertEqual("content2", self._GetDeviceFile("dex/ip2")) | 
 |  | 
 |   def testDeletesFile(self): | 
 |  | 
 |     self._CreateRemoteManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     self._PutDeviceFile("dex/ip2", "content2") | 
 |     self._PutDeviceFile("install_timestamp", "1") | 
 |     self._mock_adb.package_timestamp = "1" | 
 |  | 
 |     self._CreateZip("zip1", ("zp1", "content1")) | 
 |     self._CreateLocalManifest("zip1 zp1 ip1 0") | 
 |  | 
 |     self.assertTrue(self._GetDeviceAppPath("dex/ip2") in self._mock_adb.files) | 
 |     self._CallIncrementalInstall(incremental=True) | 
 |     self.assertFalse(self._GetDeviceAppPath("dex/ip2") in self._mock_adb.files) | 
 |  | 
 |   def testNothingToUpdate(self): | 
 |     self._CreateRemoteManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     self._PutDeviceFile("dex/ip2", "content2") | 
 |     self._PutDeviceFile("dex/ip3", "content3") | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=True) | 
 |     self.assertEqual("content1", self._GetDeviceFile("dex/ip1")) | 
 |     self.assertEqual("content2", self._GetDeviceFile("dex/ip2")) | 
 |     self.assertEqual("content3", self._GetDeviceFile("dex/ip3")) | 
 |  | 
 |   def testNoResourcesToUpdate(self): | 
 |     self._CreateRemoteManifest("zip1 zp1 ip1 0") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     # The local file is actually "resource apk", but the checksum on the device | 
 |     # for the resources file is set to be the same as the checksum for the | 
 |     # local file so that we can confirm that it was not updated. | 
 |     self._PutDeviceFile("resources.ap_", "resources") | 
 |     self._PutDeviceFile("resources_checksum", | 
 |                         incremental_install.Checksum(self._RESOURCE_APK)) | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest("zip1 zp1 ip1 0") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=True) | 
 |     self.assertEqual("resources", self._GetDeviceFile("resources.ap_")) | 
 |  | 
 |   def testUpdateResources(self): | 
 |     self._CreateRemoteManifest("zip1 zp1 ip1 0") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     self._PutDeviceFile("resources.ap_", "resources") | 
 |     self._PutDeviceFile("resources_checksum", "checksum") | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest("zip1 zp1 ip1 0") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=True) | 
 |     self.assertEqual("resource apk", self._GetDeviceFile("resources.ap_")) | 
 |  | 
 |   def testNoDevice(self): | 
 |     self._mock_adb.SetError(1, "", "device not found") | 
 |     try: | 
 |       self._CallIncrementalInstall(incremental=True) | 
 |       self.fail("Should have quit if there is no device") | 
 |     except SystemExit as e: | 
 |       # make sure it's the right SystemExit reason | 
 |       self.assertTrue("Device not found" in str(e)) | 
 |  | 
 |   def testUnauthorizedDevice(self): | 
 |     self._mock_adb.SetError(1, "", "device unauthorized. Please check the " | 
 |                             "confirmation dialog on your device") | 
 |     try: | 
 |       self._CallIncrementalInstall(incremental=True) | 
 |       self.fail("Should have quit if the device is unauthorized.") | 
 |     except SystemExit as e: | 
 |       # make sure it's the right SystemExit reason | 
 |       self.assertTrue("Device unauthorized." in str(e)) | 
 |  | 
 |   def testInstallFailure(self): | 
 |     self._mock_adb.SetError(0, "Failure", "INSTALL_FAILED", for_arg="install") | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest("zip1 zp1 ip1 0") | 
 |     try: | 
 |       self._CallIncrementalInstall(incremental=False) | 
 |       self.fail("Should have quit if the install failed.") | 
 |     except SystemExit as e: | 
 |       # make sure it's the right SystemExit reason | 
 |       self.assertTrue("Failure" in str(e)) | 
 |  | 
 |   def testStartCold(self): | 
 |     # Based on testUploadToPristineDevice | 
 |     self._CreateZip() | 
 |  | 
 |     with open("dex1", "wb") as f: | 
 |       f.write(b"content3") | 
 |  | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 0", | 
 |         "dex1 - ip3 0") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=False, start_type="cold") | 
 |  | 
 |     self.assertTrue(("monkey -p %s -c android.intent.category.LAUNCHER 1" % | 
 |                      self._APP_PACKAGE) in self._mock_adb.shell_cmdlns) | 
 |  | 
 |   def testDebugStart(self): | 
 |     self._CreateZip() | 
 |  | 
 |     with open("dex1", "wb") as f: | 
 |       f.write(b"content3") | 
 |  | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zp2 ip2 0", | 
 |         "dex1 - ip3 0") | 
 |  | 
 |     self._CallIncrementalInstall(incremental=False, start_type="debug") | 
 |     enable_debug_cmd = ("am set-debug-app -w --persistent %s" % | 
 |                         self._APP_PACKAGE) | 
 |     start_app_cmd = ("monkey -p %s -c android.intent.category.LAUNCHER 1" % | 
 |                      self._APP_PACKAGE) | 
 |     self.assertTrue(enable_debug_cmd in self._mock_adb.shell_cmdlns) | 
 |     self.assertTrue(start_app_cmd in self._mock_adb.shell_cmdlns) | 
 |  | 
 |   def testColdStop(self): | 
 |     self._CreateRemoteManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     self._PutDeviceFile("dex/ip2", "content2") | 
 |     self._PutDeviceFile("dex/ip3", "content3") | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |     self._CallIncrementalInstall(incremental=True, start_type="cold") | 
 |  | 
 |     stop_cmd = "am force-stop %s" % self._APP_PACKAGE | 
 |     self.assertTrue(stop_cmd in self._mock_adb.shell_cmdlns) | 
 |  | 
 |   def testWarmStop(self): | 
 |     self._CreateRemoteManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     self._PutDeviceFile("dex/ip2", "content2") | 
 |     self._PutDeviceFile("dex/ip3", "content3") | 
 |     self._PutDeviceFile("install_timestamp", "0") | 
 |     self._mock_adb.package_timestamp = "0" | 
 |  | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |     self._CallIncrementalInstall(incremental=True, start_type="warm") | 
 |  | 
 |     background_cmd = "input keyevent KEYCODE_APP_SWITCH" | 
 |     stop_cmd = "am kill %s" % self._APP_PACKAGE | 
 |     self.assertTrue(background_cmd in self._mock_adb.shell_cmdlns) | 
 |     self.assertTrue(stop_cmd in self._mock_adb.shell_cmdlns) | 
 |  | 
 |   def testMultipleDevicesError(self): | 
 |     errors = [ | 
 |         "more than one device and emulator", | 
 |         "more than one device", | 
 |         "more than one emulator", | 
 |     ] | 
 |     for error in errors: | 
 |       self._mock_adb.SetError(1, "", error) | 
 |       try: | 
 |         self._CallIncrementalInstall(incremental=True) | 
 |         self.fail("Should have quit if there were multiple devices.") | 
 |       except SystemExit as e: | 
 |         # make sure it's the right SystemExit reason | 
 |         self.assertTrue("Try specifying a device serial" in str(e)) | 
 |  | 
 |   def testIncrementalInstallOnPristineDevice(self): | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |  | 
 |     try: | 
 |       self._CallIncrementalInstall(incremental=True) | 
 |       self.fail("Should have quit for incremental install on pristine device") | 
 |     except SystemExit: | 
 |       pass | 
 |  | 
 |   def testIncrementalInstallWithWrongInstallTimestamp(self): | 
 |     self._CreateRemoteManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |     self._PutDeviceFile("dex/ip1", "content1") | 
 |     self._PutDeviceFile("dex/ip2", "content2") | 
 |     self._PutDeviceFile("dex/ip3", "content3") | 
 |     self._mock_adb.package_timestamp = "WRONG" | 
 |  | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest( | 
 |         "zip1 zp1 ip1 0", | 
 |         "zip1 zip2 ip2 1", | 
 |         "dex1 - ip3 0") | 
 |  | 
 |     try: | 
 |       self._CallIncrementalInstall(incremental=True) | 
 |       self.fail("Should have quit if install timestamp is wrong") | 
 |     except SystemExit: | 
 |       pass | 
 |  | 
 |   def testSdkTooOld(self): | 
 |     self._mock_adb.SetError( | 
 |         0, "INSTALL_FAILED_OLDER_SDK", "", for_arg="install") | 
 |     self._CreateZip() | 
 |     self._CreateLocalManifest("zip1 zp1 ip1 0") | 
 |     try: | 
 |       self._CallIncrementalInstall(incremental=False) | 
 |       self.fail("Should have quit if the SDK is too old.") | 
 |     except SystemExit as e: | 
 |       # make sure it's the right SystemExit reason | 
 |       self.assertTrue("minSdkVersion" in str(e)) | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |   unittest.main() |