| # Copyright 2017 Google Inc. |
| # |
| # 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. |
| |
| from __future__ import absolute_import |
| import tempfile |
| import unittest |
| |
| import fixpath # This has to be the first local import. |
| import gsutil |
| import app_info |
| from actions.action_error import ProcessError |
| import mock |
| from six.moves import range |
| |
| TEST_APP_INFO = app_info.AppInfo('test_intent', 'test_package_chrome', |
| 'test_name', 'test_version', None) |
| REPORT_DATA = {'report_folder': 'report/folder', |
| 'platform': 'Android', |
| 'report_file': 'test_1', |
| 'description': 'description', |
| 'start_time': '2019-01-09T09:12:21.111', |
| 'stop_time': '2019-01-09T09:12:22.111'} |
| |
| |
| class TestGsutilDownload(unittest.TestCase): |
| |
| def setUp(self): |
| super(TestGsutilDownload, self).setUp() |
| self.temp_mkdir_mock = mock.patch('tempfile.mkdtemp', autospec=True).start() |
| self.temp_mkdir_mock.return_value = '/tmp/temp_folder' |
| |
| @mock.patch('subprocess.check_output', autospec=True) |
| @mock.patch('device_info.GetAndroidCPUInformation', autospec=True) |
| @mock.patch('device_info.GetAndroidAPILevel', autospec=True) |
| @mock.patch('device_info.GetAndroidBuildType', autospec=True) |
| @mock.patch('subprocess.check_call', autospec=True) |
| def testDownloadAndroidApp(self, mock_check_call, mock_device_info_build_type, |
| mock_device_info_api, mock_device_info_cpu, |
| mock_check_output): |
| test_version = '12.34.56.78' |
| expected_string = '%s/%s/\n' % (gsutil._GSUTIL_BUCKET_PREFIX, |
| test_version) |
| mock_check_output.return_value = expected_string |
| mock_device_info_cpu.return_value = 'arm' |
| mock_device_info_api.side_effect = [ |
| 19, |
| 23, |
| 25, |
| 20, |
| 26, |
| 22, |
| ] |
| mock_device_info_build_type.side_effect = [ |
| 'user', |
| 'userdebug', |
| ] |
| test_app_path_chrome = ('gs://chrome-signed/android-B0urB0N' |
| '/12.34.56.78/arm/ChromeBeta.apk') |
| test_app_path_chrome_modern = ('gs://chrome-signed/android-B0urB0N' |
| '/12.34.56.78/arm/ChromeModernBeta.apk') |
| test_app_path_monochrome = ('gs://chrome-signed/android-B0urB0N' |
| '/12.34.56.78/arm/MonochromeBeta.apk') |
| test_app_path_webview = ('gs://chrome-signed/android-B0urB0N' |
| '/12.34.56.78/arm/AndroidWebview.apk') |
| test_app_path_webview_unsigned = ('gs://chrome-unsigned/android-B0urB0N' |
| '/12.34.56.78/arm/AndroidWebview.apk') |
| tmp_dir = tempfile.mkdtemp() |
| channel = 'Beta' |
| device_id = 'ZX1G223BPN' |
| gsutil.DownloadAndroidApp(test_version, channel, device_id, False) |
| self.assertEqual(mock_check_call.call_args_list[0][0][0], |
| ['gsutil', 'cp', test_app_path_chrome, tmp_dir]) |
| gsutil.DownloadAndroidApp(test_version, channel, device_id, False) |
| self.assertEqual(mock_check_call.call_args_list[1][0][0], |
| ['gsutil', 'cp', test_app_path_chrome_modern, tmp_dir]) |
| gsutil.DownloadAndroidApp(test_version, channel, device_id, False) |
| self.assertEqual(mock_check_call.call_args_list[2][0][0], |
| ['gsutil', 'cp', test_app_path_monochrome, tmp_dir]) |
| gsutil.DownloadAndroidApp(test_version, channel, device_id, True) |
| self.assertEqual(mock_check_call.call_args_list[3][0][0], |
| ['gsutil', 'cp', test_app_path_webview, tmp_dir]) |
| gsutil.DownloadAndroidApp(test_version, channel, device_id, True) |
| self.assertEqual(mock_check_call.call_args_list[4][0][0], |
| ['gsutil', 'cp', test_app_path_monochrome, tmp_dir]) |
| gsutil.DownloadAndroidApp(test_version, channel, device_id, True) |
| self.assertEqual(mock_check_call.call_args_list[5][0][0], |
| ['gsutil', 'cp', test_app_path_webview_unsigned, tmp_dir]) |
| |
| @mock.patch('subprocess.check_output', autospec=True) |
| @mock.patch('subprocess.call', autospec=True) |
| @mock.patch('logging.error', autospec=True) |
| def testGetLatestChromeVersion(self, mock_log, mock_subprocess_call, |
| mock_subprocess_check_output): |
| test_ver = '1.1.1.%s/' |
| test_values = [] |
| for i in range(2, 7): |
| test_str = 'gs://chrome-signed/android-B0urB0N/%s' % (test_ver % i) |
| test_values.append(test_str) |
| # Manually add at end to make sure sorting works. |
| test_str = 'gs://chrome-signed/android-B0urB0N/%s' % (test_ver % 1) |
| test_values.append(test_str) |
| |
| mock_subprocess_check_output.return_value = '\n'.join(test_values) |
| mock_subprocess_call.return_value = 0 |
| self.assertEqual( |
| '1.1.1.6', |
| gsutil.GetLatestChromeVersion( |
| 'gs://chrome-signed/android-B0urB0N', 'arm_64', |
| 'AndroidWebview.apk')) |
| |
| mock_subprocess_check_output.return_value = 'unmatching string' |
| mock_subprocess_call.return_value = 0 |
| self.assertEqual( |
| '0.0.0.0', |
| gsutil.GetLatestChromeVersion( |
| 'gs://chrome-signed/android-B0urB0N', 'arm_64', |
| 'AndroidWebview.apk')) |
| self.assertTrue(mock_log.called) |
| |
| mock_subprocess_check_output.return_value = '\n'.join(test_values) |
| mock_subprocess_call.return_value = 1 |
| self.assertEqual( |
| '0.0.0.0', |
| gsutil.GetLatestChromeVersion( |
| 'gs://chrome-signed/android-B0urB0N', 'arm_64', |
| 'AndroidWebview.apk')) |
| |
| def testGetGsutilUploadPath(self): |
| name = 'report_name' |
| result = gsutil._GetGsutilUploadPath(name, TEST_APP_INFO, |
| 'Android') |
| self.assertEqual( |
| result, 'gs://franky-reports/android/test_version_test_name/%s' % name) |
| webview_app_info = app_info.AppInfo('test_intent', 'test_package', |
| 'test_name', 'test_version', 'webview') |
| result = gsutil._GetGsutilUploadPath(name, webview_app_info, |
| 'Android') |
| self.assertEqual( |
| result, |
| 'gs://franky-reports/android/webview/test_version_test_name/%s' % name) |
| |
| @mock.patch('subprocess.check_output', autospec=True) |
| @mock.patch('gsutil._GetGsutilUploadPath', autospec=True) |
| def testCopyHTMLReportToCloudStorage(self, mock_path, mock_subprocess): |
| mock_path.return_value = 'some_path' |
| report_name = 'test_file_name' |
| gsutil.CopyHTMLReportToCloudStorage(report_name, 'some_path') |
| result_cmd = [ |
| 'gsutil', 'cp', '-v', '-z', 'html', '-a', 'public-read', report_name, |
| 'some_path' |
| ] |
| self.assertEqual(mock_subprocess.call_args_list[0][0][0], result_cmd) |
| |
| @mock.patch('tempfile.NamedTemporaryFile', autospec=True) |
| @mock.patch('gsutil.GetPackagePathOnDevice', autospec=True) |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| def testPullAppFoundPackage(self, mock_adb_call, mock_get_package, mock_tmp): |
| tmp_file = '/tmp/temp_folder/temp_file' |
| mock_adb_call.return_value = '' |
| mock_tmp.return_value.name = tmp_file |
| test_output = gsutil.PullApp('com.sample.test_package', |
| 'device_id') |
| self.assertIn(tmp_file, test_output) |
| self.assertTrue(mock_get_package.called) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| def testGetPackagePathOnDeviceNotFoundPackage(self, mock_adb_call): |
| not_found_package = 'com.not.found.package' |
| msg = 'Not found any apk for package %s!' % not_found_package |
| mock_adb_call.return_value = '' |
| try: |
| gsutil.GetPackagePathOnDevice(not_found_package, 'device_id') |
| raise Exception('"Package not found" exception not occurred!') |
| except ProcessError as expected: |
| self.assertEqual(expected.message, msg) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| def testGetPackagePathOnDeviceFoundPackage(self, mock_adb_call): |
| package = 'com.found.package' |
| package_path = '/data/app/%s-cache/base.apk' % package |
| mock_adb_call.return_value = 'package:%s' % package_path |
| path = gsutil.GetPackagePathOnDevice(package, 'device_id') |
| self.assertEqual('/data/app/%s-cache/base.apk' % package, path) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| def testGetPackagePathOnDeviceFoundSystemPackage(self, mock_adb_call): |
| package = 'com.found.package' |
| package_path = '/system/priv-app/SysPackage/SysPackage.apk' |
| mock_adb_call.return_value = 'package:%s' % package_path |
| path = gsutil.GetPackagePathOnDevice(package, 'device_id') |
| self.assertEqual('/system/priv-app/SysPackage/SysPackage.apk', path) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| def testGetPackagePathOnDeviceNotFoundBaseApk(self, mock_adb_call): |
| package = 'com.found.package' |
| package_path = '\n'.join([ |
| '/data/app/%s-cache/not_base.apk' % package, |
| '/data/app/%s-cache/additional_base.apk' % package |
| ]) |
| mock_adb_call.return_value = 'package:%s' % package_path |
| msg = 'Not found %s apk for package %s!' % ('base.apk', package) |
| try: |
| gsutil.GetPackagePathOnDevice(package, 'device_id') |
| raise Exception('"base.apk not found" exception not occurred!') |
| except ProcessError as expected: |
| self.assertEqual(expected.message, msg) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| @mock.patch('gsutil.GetPackagePathOnDevice', autospec=True) |
| @mock.patch('gsutil._CopyFileOnSdcard', autospec=True) |
| def testPullApp(self, mock_copy_on_sdcard, mock_get_package_path, |
| mock_adb_call): |
| mock_adb_call.return_value = '' |
| mock_get_package_path.return_value = '/data/app/package_name' |
| gsutil.PullApp('package-1', 'device_id') |
| self.assertEqual(0, len(mock_copy_on_sdcard.mock_calls)) |
| self.assertEqual(1, len(mock_adb_call.mock_calls)) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| @mock.patch('gsutil.GetPackagePathOnDevice', autospec=True) |
| @mock.patch('gsutil._CopyFileOnSdcard', autospec=True) |
| def testPullAppNotAllowToCopyData(self, mock_copy_on_sdcard, |
| mock_get_package_path, mock_adb_call): |
| mock_adb_call.return_value = ''.join([ |
| 'adb: error: remote object ', |
| '\'/data/app/package/base.apk\' does not exist' |
| ]) |
| mock_get_package_path.return_value = '/data/app/package_name' |
| gsutil.PullApp('package-1', 'device_id') |
| self.assertEqual(1, len(mock_copy_on_sdcard.mock_calls)) |
| self.assertEqual(3, len(mock_adb_call.mock_calls)) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| def testCopyFileOnSdcard(self, mock_adb_call): |
| mock_adb_call.return_value = '' |
| gsutil._CopyFileOnSdcard('/data/app/package-1/base.apk', |
| 'device_id') |
| self.assertEqual(2, len(mock_adb_call.mock_calls)) |
| |
| @mock.patch('utilities.util.RunADBProcess', autospec=True) |
| def testCopyFileOnSdcardOnDeviceWithoutSdcard(self, mock_adb_call): |
| mock_adb_call.return_value = 'No /sdcard/ on device' |
| try: |
| gsutil._CopyFileOnSdcard('/data/app/package-1/base.apk', |
| 'device_id') |
| raise Exception('"Not sdcard on the device!" exception not occurred!') |
| except ProcessError as expected: |
| self.assertEqual( |
| expected.message, ''.join([ |
| 'Can not copy file /data/app/package-1/base.apk ', |
| 'to /sdcard/ (no sdcard on device_id!' |
| ])) |
| self.assertEqual(1, len(mock_adb_call.mock_calls)) |
| |
| @mock.patch('subprocess.check_call', autospec=True) |
| @mock.patch('gsutil._GetGsutilUploadPath', autospec=True) |
| def testUploadFolder(self, mock_path, mock_check_call): |
| mock_path.return_value = 'some_path' |
| report_data = REPORT_DATA |
| report_data['copy_to_cloud_storage'] = True |
| report_data['webview_provider_package'] = 'N/A' |
| gsutil.UploadFolder('report/folder', 'gs_path') |
| result_cmd = ['gsutil', 'cp', '-v', '-a', 'public-read', |
| '-r', 'report/folder', 'gs_path'] |
| self.assertEqual(mock_check_call.call_args_list[0][0][0], result_cmd) |
| |
| @mock.patch('tarfile.open', autospec=True) |
| @mock.patch('zipfile.ZipFile', autospec=True) |
| @mock.patch('subprocess.check_output', autospec=True) |
| @mock.patch('subprocess.check_call', autospec=True) |
| def testDownloadIOSApp(self, mock_check_call, mock_check_output, mock_tar, |
| mock_zip): |
| test_version = '12.34.56.78' |
| expected_string = '%s/%s/\n' % (gsutil._IOS_GSUTIL_BUCKET_PREFIX, |
| test_version) |
| mock_check_output.return_value = expected_string |
| |
| test_app_path_chrome = ('gs://bling-archive' |
| '/12.34.56.78/*/*/*/*/beta.tar.gz') |
| tmp_dir = tempfile.mkdtemp() |
| mock_tar.return_value.name = 'beta.tar.gz' |
| mock_zip.return_value.name = 'beta.ipa' |
| channel = 'Beta' |
| gsutil.DownloadIOSApp(test_version, channel) |
| self.assertEqual(mock_check_call.call_args_list[0][0][0], |
| ['gsutil', 'cp', test_app_path_chrome, tmp_dir]) |
| |
| @mock.patch('subprocess.check_output', autospec=True) |
| def testGetLatestIOSChromeVersion(self, mock_subprocess_check_output): |
| test_ver = '1.1.1.%s/' |
| test_values = [] |
| for i in range(2, 7): |
| test_str = 'gs://bling-archive/%s' % (test_ver % i) |
| test_values.append(test_str) |
| # Manually add at end to make sure sorting works. |
| test_str = 'gs://bling-archive/%s' % (test_ver % 1) |
| test_values.append(test_str) |
| |
| mock_subprocess_check_output.return_value = '\n'.join(test_values) |
| self.assertEqual( |
| '1.1.1.6', |
| gsutil.GetLatestIOSChromeVersion(channel='Canary')) |
| |
| if __name__ == '__main__': |
| unittest.main() |