async def test_extract_all_apps(mocker, tmpdir, suffix, command, raises): """``extract_all_apps`` creates ``parent_dir`` and raises if any tar command fails. The ``run_command`` calls all start with a commandline that calls ``tar``. """ async def fake_run_command(*args, **kwargs): assert args[0][0] == command if raises: raise IScriptError("foo") mocker.patch.object(mac, "run_command", new=fake_run_command) work_dir = os.path.join(str(tmpdir), "work") config = {"work_dir": work_dir, "dmg_prefix": "test"} all_paths = [ mac.App(orig_path=os.path.join(work_dir, f"orig1.{suffix}")), mac.App(orig_path=os.path.join(work_dir, f"orig2.{suffix}")), mac.App(orig_path=os.path.join(work_dir, f"orig3.{suffix}")), ] if raises: with pytest.raises(IScriptError): await mac.extract_all_apps(config, all_paths) else: await mac.extract_all_apps(config, all_paths) for i in ("0", "1", "2"): assert os.path.isdir(os.path.join(work_dir, i))
async def test_copy_pkgs_to_artifact_dir(tmpdir, artifact_prefix): """``copy_pkgs_to_artifact_dir`` creates all needed parent directories and copies pkg artifacts successfully. """ num_pkgs = 3 work_dir = os.path.join(str(tmpdir), "work") artifact_dir = os.path.join(str(tmpdir), "artifact") config = {"artifact_dir": artifact_dir, "work_dir": work_dir} all_paths = [] expected_paths = [] for i in range(num_pkgs): app = mac.App( pkg_path=os.path.join(work_dir, str(i), "target.pkg".format(i)), artifact_prefix=artifact_prefix, orig_path=os.path.join( work_dir, f"cot/taskId/{artifact_prefix}build/{i}/target-{i}.tar.gz" ), ) expected_path = os.path.join( artifact_dir, f"{artifact_prefix}build/{i}/target-{i}.pkg" ) expected_paths.append(expected_path) makedirs(os.path.dirname(app.pkg_path)) with open(app.pkg_path, "w") as fh: fh.write(expected_path) all_paths.append(app) await mac.copy_pkgs_to_artifact_dir(config, all_paths) for i in range(num_pkgs): expected_path = expected_paths[i] assert os.path.exists(expected_path) assert expected_path == all_paths[i].target_pkg_path with open(expected_path) as fh: assert fh.read() == expected_path
async def test_create_pkg_files(mocker, pkg_cert_id, raises): """``create_pkg_files`` runs pkgbuild concurrently for each ``App``, and raises any exceptions hit along the way. """ async def fake_run_command(cmd, **kwargs): assert cmd[0:2] == ["sudo", "pkgbuild"] if raises: raise IScriptError("foo") key_config = {"pkg_cert_id": pkg_cert_id, "signing_keychain": "signing.keychain"} config = {"concurrency_limit": 2} all_paths = [] for i in range(3): all_paths.append( mac.App( app_path="foo/{}/{}.app".format(i, i), parent_dir="foo/{}".format(i) ) ) mocker.patch.object(mac, "run_command", new=fake_run_command) if raises: with pytest.raises(IScriptError): await mac.create_pkg_files(config, key_config, all_paths) else: assert await mac.create_pkg_files(config, key_config, all_paths) is None
async def test_staple_notarization(mocker, raises): """``staple_notarization`` runs stapling concurrently for each ``App``, and raises any exceptions hit along the way. """ async def fake_retry_async(*args, **kwargs): assert kwargs["args"][0][0] == "xcrun" if raises: raise IScriptError("foo") all_paths = [] for i in range(3): parent_dir = str(i) app_name = f"{i}.app" app_path = os.path.join(parent_dir, app_name) all_paths.append( mac.App(parent_dir=parent_dir, app_name=app_name, app_path=app_path) ) mocker.patch.object(mac, "retry_async", new=fake_retry_async) if raises: with pytest.raises(IScriptError): await mac.staple_notarization(all_paths) else: assert await mac.staple_notarization(all_paths) is None
async def test_create_one_notarization_zipfile(mocker, tmpdir, raises): """``create_one_notarization_zipfile`` calls the expected cmdline, and raises on failure. """ work_dir = str(tmpdir) async def fake_run_command(*args, **kwargs): assert args[0] == [ "zip", "-r", os.path.join(work_dir, "app_path.zip"), "0/0.app", "1/1.app", "2/2.app", ] if raises: raise IScriptError("foo") mocker.patch.object(mac, "run_command", new=fake_run_command) all_paths = [] for i in range(3): all_paths.append( mac.App(app_path=os.path.join(work_dir, str(i), "{}.app".format(i))) ) if raises: with pytest.raises(IScriptError): await mac.create_one_notarization_zipfile(work_dir, all_paths) else: await mac.create_one_notarization_zipfile(work_dir, all_paths)
async def test_create_all_notarization_zipfiles(mocker, tmpdir, raises): """``create_all_notarization_zipfiles`` calls ``zip -r``, and raises on failure. """ async def fake_run_command(*args, **kwargs): assert args[0][0:2] == ["zip", "-r"] if raises: raise IScriptError("foo") mocker.patch.object(mac, "run_command", new=fake_run_command) all_paths = [] work_dir = str(tmpdir) for i in range(3): parent_dir = os.path.join(work_dir, str(i)) app_name = "fx {}.app".format(str(i)) app_path = os.path.join(parent_dir, app_name) all_paths.append( mac.App(parent_dir=parent_dir, app_name=app_name, app_path=app_path) ) if raises: with pytest.raises(IScriptError): await mac.create_all_notarization_zipfiles(all_paths) else: await mac.create_all_notarization_zipfiles(all_paths)
async def test_verify_app_signature_noop(mocker): """``verify_app_signature`` is noop when ``verify_mac_signature`` is False.""" key_config = {"verify_mac_signature": False} # If we actually run_command, raise to show we're doing too much mocker.patch.object(mac, "run_command", new=fail_async) await mac.verify_app_signature(key_config, mac.App())
async def test_sign_all_apps(mocker, tmpdir, raises): """``sign_all_apps`` calls ``sign`` and raises on failure. """ key_config = {"x": "y", "signing_keychain": "keychain", "keychain_password": "******"} config = {} entitlements_path = "fake_entitlements_path" work_dir = str(tmpdir) all_paths = [] app_paths = [] for i in range(3): app_path = "{}.app".format(str(i)) app_paths.append(app_path) all_paths.append(mac.App(parent_dir=os.path.join(work_dir, str(i)), app_path=app_path)) async def fake_sign(arg1, arg2, arg3): assert arg1 == key_config assert arg2 in app_paths assert arg3 == entitlements_path if raises: raise IScriptError("foo") mocker.patch.object(mac, "set_app_path_and_name", return_value=None) mocker.patch.object(mac, "sign_app", new=fake_sign) mocker.patch.object(mac, "unlock_keychain", new=noop_async) mocker.patch.object(mac, "verify_app_signature", new=noop_async) mocker.patch.object(mac, "sign_widevine_dir", new=noop_async) if raises: with pytest.raises(IScriptError): await mac.sign_all_apps(config, key_config, entitlements_path, all_paths) else: await mac.sign_all_apps(config, key_config, entitlements_path, all_paths)
async def test_tar_apps(mocker, tmpdir, raises, artifact_prefix): """``tar_apps`` runs tar concurrently for each ``App``, creating the app ``target_tar_path``s, and raises any exceptions hit along the way. """ async def fake_raise_future_exceptions(futures): await asyncio.wait(futures) if raises: raise IScriptError("foo") work_dir = os.path.join(tmpdir, "work") config = {"artifact_dir": os.path.join(tmpdir, "artifact")} all_paths = [] expected = [] for i in range(3): parent_dir = os.path.join(work_dir, str(i)) app_name = "{}.app".format(i) makedirs(parent_dir) # touch parent_dir/app_name with open(os.path.join(parent_dir, app_name), "w") as fh: fh.write("foo") orig_path = os.path.join( work_dir, "cot", "foo", artifact_prefix, "build", str(i), f"{i}.tar.gz" ) # overload pkg_path to track i all_paths.append( mac.App( parent_dir=parent_dir, app_name=app_name, app_path=os.path.join(parent_dir, app_name), artifact_prefix=artifact_prefix, orig_path=orig_path, pkg_path=str(i), ) ) expected.append( os.path.join( config["artifact_dir"], artifact_prefix, "build", "{}/{}.tar.gz".format(i, i), ) ) mocker.patch.object(mac, "run_command", new=noop_async) mocker.patch.object( mac, "raise_future_exceptions", new=fake_raise_future_exceptions ) if raises: with pytest.raises(IScriptError): await mac.tar_apps(config, all_paths) else: assert await mac.tar_apps(config, all_paths) is None assert [x.target_tar_path for x in all_paths] == expected for path in expected: assert os.path.isdir(os.path.dirname(path))
async def test_wrap_notarization_with_sudo(mocker, tmpdir, raises): """``wrap_notarization_with_sudo`` chunks its requests into one concurrent request per each of the ``local_notarization_accounts``. It doesn't log the password. """ futures_len = [3, 3, 2] pw = "test_apple_password" async def fake_retry_async(_, args, kwargs, **kw): cmd = args[0] end = len(cmd) - 1 assert cmd[0] == "sudo" log_cmd = kwargs["log_cmd"] assert cmd[0:end] == log_cmd[0:end] assert cmd[end] != log_cmd[end] assert cmd[end] == pw assert log_cmd[end].replace("*", "") == "" async def fake_raise_future_exceptions(futures, **kwargs): """``raise_future_exceptions`` mocker.""" await asyncio.wait(futures) assert len(futures) == futures_len.pop(0) if raises: raise IScriptError("foo") def fake_get_uuid_from_log(path): return path work_dir = str(tmpdir) config = {"local_notarization_accounts": ["acct0", "acct1", "acct2"]} key_config = { "base_bundle_id": "org.iscript.test", "apple_notarization_account": "test_apple_account", "apple_notarization_password": pw, "apple_asc_provider": "apple_asc_provider", } all_paths = [] expected = {} # Let's create 8 apps, with 3 sudo accounts, so we expect batches of 3, 3, 2 for i in range(8): parent_dir = os.path.join(work_dir, str(i)) notarization_log_path = f"{parent_dir}-notarization.log" all_paths.append(mac.App(parent_dir=parent_dir, zip_path=os.path.join(parent_dir, "{}.zip".format(i)))) expected[notarization_log_path] = notarization_log_path mocker.patch.object(mac, "retry_async", new=fake_retry_async) mocker.patch.object(mac, "raise_future_exceptions", new=fake_raise_future_exceptions) mocker.patch.object(mac, "get_uuid_from_log", new=fake_get_uuid_from_log) if raises: with pytest.raises(IScriptError): await mac.wrap_notarization_with_sudo(config, key_config, all_paths) else: assert await mac.wrap_notarization_with_sudo(config, key_config, all_paths) == expected
def test_app_path_and_name(mocker): """``app_path_and_name`` sets the ``app_path`` and ``app_name`` if not already set. """ def fake_get_app_dir(parent_dir): x = os.path.basename(parent_dir) return os.path.join(parent_dir, "{}.app".format(x)) all_paths = [ mac.App(parent_dir="foo/1"), mac.App(parent_dir="foo/2", app_path="foo/2/2.app"), mac.App(parent_dir="foo/3", app_path="foo/4/4.app", app_name="4.app"), ] mocker.patch.object(mac, "get_app_dir", new=fake_get_app_dir) expected = [["foo/1/1.app", "1.app"], ["foo/2/2.app", "2.app"], ["foo/4/4.app", "4.app"]] for app in all_paths: mac.set_app_path_and_name(app) assert [app.app_path, app.app_name] == expected.pop(0)
def test_app(): """``App`` attributes can be set, and ``check_required_attrs`` raises if the required attrs aren't set. """ a = mac.App() assert a.orig_path == "" a.orig_path = "foo" assert a.orig_path == "foo" a.check_required_attrs(["orig_path"]) with pytest.raises(IScriptError): a.check_required_attrs(["app_path"])
async def test_sign_geckodriver(exists, mocker, tmpdir): """Render ``sign_geckodriver`` noop and verify we have complete code coverage. """ key_config = {"identity": "id", "signing_keychain": "keychain"} config = {"artifact_dir": os.path.join(tmpdir, "artifacts")} app = mac.App( orig_path=os.path.join(tmpdir, "cot/task1/public/build/geckodriver.tar.gz"), parent_dir=os.path.join(tmpdir, "0"), artifact_prefix=os.path.join("public/build"), ) makedirs(app.parent_dir) if exists: touch(os.path.join(app.parent_dir, "geckodriver")) mocker.patch.object(mac, "run_command", new=noop_async) if exists: await mac.sign_geckodriver(config, key_config, [app]) else: with pytest.raises(IScriptError): await mac.sign_geckodriver(config, key_config, [app])