def test_no_install(mock_command, tmp_path): "If an SDK is not available, and install is not requested, an error is raised" # Call `verify()` with pytest.raises(MissingToolError): AndroidSDK.verify(mock_command, jdk=MagicMock(), install=False) assert mock_command.download_url.call_count == 0
def test_raises_networkfailure_on_connectionerror(mock_command): "If an error occurs downloading the ZIP file, and error is raised." mock_command.download_url.side_effect = requests_exceptions.ConnectionError() with pytest.raises(NetworkFailure): AndroidSDK.verify(mock_command, jdk=MagicMock()) # The download was attempted mock_command.download_url.assert_called_once_with( url="https://dl.google.com/android/repository/sdk-tools-unknown-4333796.zip", download_path=mock_command.tools_path, ) # But no unpack occurred assert mock_command.shutil.unpack_archive.call_count == 0
def mock_sdk(tmp_path): command = MagicMock() command.home_path = tmp_path command.host_platform = 'unknown' sdk = AndroidSDK(command, root_path=tmp_path) # Mock some existing emulators sdk.emulators = MagicMock(return_value=[ 'runningEmulator', 'idleEmulator', ]) return sdk
def verify_tools(self): """ Verify that we the Android APK tools in `briefcase` will operate on this system, downloading tools as needed. """ super().verify_tools() self.android_sdk = AndroidSDK.verify(self)
def test_invalid_user_provided_sdk(mock_command, tmp_path): "If the user specifies an invalid ANDROID_SDK_ROOT, it is ignored" # Create `sdkmanager` and the license file # for the *briefcase* SDK. android_sdk_root_path = tmp_path / "tools" / "android_sdk" tools_bin = android_sdk_root_path / "tools" / "bin" tools_bin.mkdir(parents=True, mode=0o755) (tools_bin / "sdkmanager").touch(mode=0o755) # Pre-accept the license accept_license(android_sdk_root_path)() # Set the environment to specify an ANDROID_SDK_ROOT that doesn't exist mock_command.os.environ = { 'ANDROID_SDK_ROOT': str(tmp_path / "other_sdk") } # Expect verify() to succeed sdk = AndroidSDK.verify(mock_command, jdk=MagicMock()) # No calls to download, run or unpack anything. mock_command.download_url.assert_not_called() mock_command.subprocess.run.assert_not_called() mock_command.subprocess.check_output.assert_not_called() mock_command.shutil.unpack_archive.assert_not_called() # The returned SDK has the expected root path. assert sdk.root_path == android_sdk_root_path
def test_user_provided_sdk(mock_command, tmp_path): "If the user specifies a valid ANDROID_SDK_ROOT, it is used" # Create `sdkmanager` and the license file. existing_android_sdk_root_path = tmp_path / "other_sdk" tools_bin = existing_android_sdk_root_path / "tools" / "bin" tools_bin.mkdir(parents=True, mode=0o755) (tools_bin / "sdkmanager").touch(mode=0o755) # Pre-accept the license accept_license(existing_android_sdk_root_path)() # Set the environment to specify ANDROID_SDK_ROOT mock_command.os.environ = { 'ANDROID_SDK_ROOT': str(existing_android_sdk_root_path) } # Expect verify() to succeed sdk = AndroidSDK.verify(mock_command, jdk=MagicMock()) # No calls to download, run or unpack anything. mock_command.download_url.assert_not_called() mock_command.subprocess.run.assert_not_called() mock_command.subprocess.check_output.assert_not_called() mock_command.shutil.unpack_archive.assert_not_called() # The returned SDK has the expected root path. # FIXME: The conversion to str is needed for Python 3.5 compatibility. assert str(sdk.root_path) == str(existing_android_sdk_root_path)
def mock_sdk(tmp_path): command = MagicMock() command.home_path = tmp_path # For default test purposes, assume we're on macOS x86_64 command.host_os = "Darwin" command.host_arch = "x86_64" sdk = AndroidSDK(command, jdk=MagicMock(), root_path=tmp_path) # Mock some existing emulators sdk.emulators = MagicMock(return_value=[ "runningEmulator", "idleEmulator", ]) return sdk
def mock_sdk(tmp_path): command = MagicMock() command.logger = Log() command.input = DummyConsole() sdk = AndroidSDK(command, jdk=MagicMock(), root_path=tmp_path) sdk.devices = MagicMock( return_value={ "041234567892009a": { "name": "Unknown device (not authorized for development)", "authorized": False, }, "KABCDABCDA1513": { "name": "Kogan Agora 9", "authorized": True, }, "emulator-5554": { "name": "Android SDK built for x86", "authorized": True, }, }) sdk.emulators = MagicMock(return_value=[ "runningEmulator", "idleEmulator", ]) # Set up an ADB for each device. def mock_adb(device_id): adb = MagicMock() if device_id == "emulator-5554": adb.avd_name.return_value = "runningEmulator" else: adb.avd_name.return_value = None return adb sdk.adb = mock_adb return sdk
def mock_sdk(tmp_path): command = MagicMock() command.input = DummyConsole() sdk = AndroidSDK(command, root_path=tmp_path) sdk.devices = MagicMock( return_value={ '041234567892009a': { 'name': 'Unknown device (not authorized for development)', 'authorized': False, }, 'KABCDABCDA1513': { 'name': 'Kogan_Agora_9', 'authorized': True, }, 'emulator-5554': { 'name': 'generic_x86', 'authorized': True, }, }) sdk.emulators = MagicMock(return_value=[ 'runningEmulator', 'idleEmulator', ]) # Set up an ADB for each device. def mock_adb(device_id): adb = MagicMock() if device_id == 'emulator-5554': adb.avd_name.return_value = 'runningEmulator' else: adb.avd_name.return_value = None return adb sdk.adb = mock_adb return sdk
def mock_sdk(tmp_path): command = MagicMock() command.home_path = tmp_path command.subprocess = MagicMock() command.input = DummyConsole() # Mock an empty environment command.os.environ = {} # Set a JAVA_HOME command.java_home_path = Path('/path/to/jdk') sdk = AndroidSDK(command, root_path=tmp_path / 'sdk') return sdk
def run_command(tmp_path, first_app_config): command = GradleRunCommand(base_path=tmp_path / "base_path") command.dot_briefcase_path = tmp_path / ".briefcase" command.java_home_path = tmp_path / "java" command.mock_adb = MagicMock() command.android_sdk = AndroidSDK(command, root_path=tmp_path) command.android_sdk.adb = MagicMock(return_value=command.mock_adb) command.os = MagicMock() command.os.environ = {} command.requests = MagicMock() command.subprocess = MagicMock() command.sys = MagicMock() return command
def test_detects_bad_zipfile(mock_command, tmp_path): "If the ZIP file is corrupted, an error is raised." android_sdk_root_path = tmp_path / "tools" / "android_sdk" # The download will produce a cached file cache_file = MagicMock() cache_file.__str__.return_value = "/path/to/download.zip" mock_command.download_url.return_value = cache_file # But the unpack will fail. mock_command.shutil.unpack_archive.side_effect = shutil.ReadError with pytest.raises(BriefcaseCommandError): AndroidSDK.verify(mock_command, jdk=MagicMock()) # The download attempt was made. mock_command.download_url.assert_called_once_with( url="https://dl.google.com/android/repository/sdk-tools-unknown-4333796.zip", download_path=mock_command.tools_path, ) mock_command.shutil.unpack_archive.assert_called_once_with( "/path/to/download.zip", extract_dir=str(android_sdk_root_path) )
def test_download_sdk(mock_command, tmp_path, host_os): "If an SDK is not available, one will be downloaded" android_sdk_root_path = tmp_path / "tools" / "android_sdk" # Mock-out `host_os` so we only do our permission check on non-Windows. mock_command.host_os = host_os # The download will produce a cached file cache_file = MagicMock() cache_file.__str__.return_value = "/path/to/download.zip" mock_command.download_url.return_value = cache_file # Create a file that would have been created by unpacking the archive example_tool = android_sdk_root_path / "tools" / "bin" / "exampletool" example_tool.parent.mkdir(parents=True) example_tool.touch(0o644) # Set up a side effect for accepting the license mock_command.subprocess.run.side_effect = accept_license(android_sdk_root_path) # Call `verify()` sdk = AndroidSDK.verify(mock_command, jdk=MagicMock()) # Validate that the SDK was downloaded and unpacked url = "https://dl.google.com/android/repository/sdk-tools-{host_os}-4333796.zip".format( host_os=host_os.lower() ) mock_command.download_url.assert_called_once_with( url=url, download_path=mock_command.tools_path, ) mock_command.shutil.unpack_archive.assert_called_once_with( "/path/to/download.zip", extract_dir=str(android_sdk_root_path) ) # The cached file will be deleeted cache_file.unlink.assert_called_once_with() # On non-Windows, ensure the unpacked binary was made executable if host_os != 'Windows': assert os.access(str(example_tool), os.X_OK) # The license has been accepted assert (android_sdk_root_path / "licenses" / "android-sdk-license").exists() # The returned SDK has the expected root path. assert sdk.root_path == android_sdk_root_path
def mock_sdk(tmp_path): command = MagicMock() command.home_path = tmp_path command.subprocess = MagicMock() command.input = DummyConsole() command.logger = Log(verbosity=1) # For default test purposes, assume we're on macOS x86_64 command.host_os = "Darwin" command.host_arch = "x86_64" # Mock an empty environment command.os.environ = {} # Set up a JDK jdk = MagicMock() jdk.java_home = Path("/path/to/jdk") sdk = AndroidSDK(command, jdk=jdk, root_path=tmp_path / "sdk") return sdk
def test_download_sdk_if_sdkmanager_not_executable(mock_command, tmp_path): """An SDK will be downloaded and unpackged if `tools/bin/sdkmanager` exists but does not have its permissions set properly.""" android_sdk_root_path = tmp_path / "tools" / "android_sdk" # Create non-executable `sdkmanager`. android_sdk_root_path = tmp_path / "tools" / "android_sdk" (android_sdk_root_path / "tools" / "bin").mkdir(parents=True) (android_sdk_root_path / "tools" / "bin" / "sdkmanager").touch(mode=0o644) # The download will produce a cached file cache_file = MagicMock() cache_file.__str__.return_value = "/path/to/download.zip" mock_command.download_url.return_value = cache_file # Set up a side effect for accepting the license mock_command.subprocess.run.side_effect = accept_license(android_sdk_root_path) # Call `verify()` sdk = AndroidSDK.verify(mock_command, jdk=MagicMock()) # Validate that the SDK was downloaded and unpacked mock_command.download_url.assert_called_once_with( url="https://dl.google.com/android/repository/sdk-tools-unknown-4333796.zip", download_path=mock_command.tools_path, ) mock_command.shutil.unpack_archive.assert_called_once_with( "/path/to/download.zip", extract_dir=str(android_sdk_root_path) ) # The cached file will be deleted cache_file.unlink.assert_called_once_with() # The license has been accepted assert (android_sdk_root_path / "licenses" / "android-sdk-license").exists() # The returned SDK has the expected root path. assert sdk.root_path == android_sdk_root_path
def test_succeeds_immediately_in_happy_path(mock_command, host_os, tmp_path): "If verify is invoked on a path containing an Android SDK, it does nothing." # If `sdkmanager` exists and has the right permissions, and # `android-sdk-license` exists, verify() should # succeed, create no subprocesses, make no requests, and return a # SDK wrapper. # On Windows, this requires `sdkmanager.bat`; on non-Windows, it requires # `sdkmanager`. # Create `sdkmanager` and the license file. android_sdk_root_path = tmp_path / "tools" / "android_sdk" tools_bin = android_sdk_root_path / "tools" / "bin" tools_bin.mkdir(parents=True, mode=0o755) if host_os == "Windows": (tools_bin / "sdkmanager.bat").touch() else: (tools_bin / "sdkmanager").touch(mode=0o755) # Pre-accept the license accept_license(android_sdk_root_path)() # Configure `mock_command` to assume the `host_os` we parameterized with. mock_command.host_os = host_os # Expect verify() to succeed sdk = AndroidSDK.verify(mock_command, jdk=MagicMock()) # No calls to download, run or unpack anything. mock_command.download_url.assert_not_called() mock_command.subprocess.run.assert_not_called() mock_command.subprocess.check_output.assert_not_called() mock_command.shutil.unpack_archive.assert_not_called() # The returned SDK has the expected root path. assert sdk.root_path == android_sdk_root_path
def mock_sdk(tmp_path): command = MagicMock() command.host_platform = 'unknown' sdk = AndroidSDK(command, root_path=tmp_path) sdk.sleep = MagicMock() sdk.mock_run = MagicMock() def mock_adb(device): adb = ADB(sdk, device) adb.run = sdk.mock_run return adb sdk.adb = mock_adb # Mock some existing emulators sdk.emulators = MagicMock(return_value=[ 'runningEmulator', 'idleEmulator', ]) return sdk