mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-19 14:07:26 +02:00
193 lines
8.8 KiB
Python
193 lines
8.8 KiB
Python
"""Check release selection and audits without building APKs or deleting artifacts."""
|
|
|
|
import json
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
FLUTTER_STUB = """import json, os, sys
|
|
from pathlib import Path
|
|
args = sys.argv[1:]
|
|
if Path(sys.argv[0]).name == 'fvm':
|
|
assert args.pop(0) == 'flutter'
|
|
with open(os.environ['BUILD_TEST_LOG'], 'a') as log:
|
|
log.write(json.dumps({'tool': Path(sys.argv[0]).name, 'args': args,
|
|
'sdk': os.environ.get('SPOTIFLAC_DISCORD_SDK', '1')}) + '\\n')
|
|
if args == ['--version', '--machine']:
|
|
print(json.dumps({'frameworkVersion': os.environ.get('BUILD_TEST_FLUTTER_VERSION', '3.47.5')}))
|
|
else:
|
|
assert args[:2] == ['build', 'apk']
|
|
output = Path('build/app/outputs/flutter-apk')
|
|
output.mkdir(parents=True, exist_ok=True)
|
|
for abi in os.environ['SPOTIFLAC_RUST_ANDROID_ABIS'].split(','):
|
|
(output / ('app-' + abi + '-release.apk')).write_bytes(b'fixture split')
|
|
(output / 'app-release.apk').write_bytes(b'fixture universal')
|
|
"""
|
|
|
|
PYTHON_STUB = """import json, os, sys
|
|
if sys.argv[1] == 'scripts/check_backend_apk.py':
|
|
with open(os.environ['BUILD_TEST_LOG'], 'a') as log:
|
|
log.write(json.dumps({'tool': 'audit', 'args': sys.argv[2:]}) + '\\n')
|
|
else:
|
|
os.execv(sys.executable, [sys.executable, *sys.argv[1:]])
|
|
"""
|
|
|
|
|
|
class AndroidBuildScriptTest(unittest.TestCase):
|
|
def setUp(self):
|
|
directory = tempfile.TemporaryDirectory()
|
|
self.addCleanup(directory.cleanup)
|
|
self.project = Path(directory.name)
|
|
(self.project / "scripts").mkdir()
|
|
shutil.copyfile(Path(__file__).with_name("build_android.sh"), self.project / "scripts/build_android.sh")
|
|
(self.project / ".fvmrc").write_text('{"flutter":"3.47.5"}')
|
|
sdk = self.project / "third_party/spotiflac_discord/sdk"
|
|
sdk.mkdir(parents=True)
|
|
(sdk / "discord_partner_sdk.aar").write_bytes(b"staged fixture")
|
|
for name in (
|
|
"notices/Discord-License-Notices.txt",
|
|
"android/prefab/modules/discord_partner_sdk/include/discordpp.h",
|
|
"android/jni/arm64-v8a/libdiscord_partner_sdk.so",
|
|
"android/jni/armeabi-v7a/libdiscord_partner_sdk.so",
|
|
):
|
|
path = sdk / name
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_bytes(b"staged fixture")
|
|
self.tools = self.project / "tools"
|
|
self.tools.mkdir()
|
|
self.log = self.project / "calls.jsonl"
|
|
self.env = os.environ.copy()
|
|
for key in ("SPOTIFLAC_DISCORD_SDK", "SPOTIFLAC_RUST_ANDROID_ABIS"):
|
|
self.env.pop(key, None)
|
|
self.env.update(PATH=str(self.tools) + os.pathsep + os.defpath, BUILD_TEST_LOG=str(self.log))
|
|
self.tool(self.tools / "python3", PYTHON_STUB)
|
|
git = self.tools / "git"
|
|
git.write_text("#!/bin/sh\necho 1234abcd\n")
|
|
git.chmod(0o755)
|
|
self.pinned = self.project / ".fvm/flutter_sdk/bin/flutter"
|
|
self.tool(self.pinned, FLUTTER_STUB)
|
|
|
|
def tool(self, path, source):
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text("#!" + sys.executable + "\n" + source)
|
|
path.chmod(0o755)
|
|
|
|
def run_build(self, *args):
|
|
return subprocess.run(
|
|
["/bin/bash", str(self.project / "scripts/build_android.sh"), *args],
|
|
cwd=self.project, env=self.env, text=True, capture_output=True,
|
|
)
|
|
|
|
def calls(self):
|
|
return [json.loads(line) for line in self.log.read_text().splitlines()]
|
|
|
|
def test_default_full_audits_two_splits_and_universal(self):
|
|
result = self.run_build("--verbose")
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
calls = self.calls()
|
|
build = next(call for call in calls if call["args"][:2] == ["build", "apk"])
|
|
self.assertIn("android-arm64,android-arm", build["args"])
|
|
self.assertIn("--verbose", build["args"])
|
|
audits = [call["args"] for call in calls if call["tool"] == "audit"]
|
|
self.assertEqual([Path(args[0]).name for args in audits], [
|
|
"app-arm64-v8a-release.apk", "app-armeabi-v7a-release.apk", "app-release.apk",
|
|
])
|
|
self.assertTrue(all("--discord-sdk" in args for args in audits))
|
|
self.assertEqual(audits[-1][audits[-1].index("--abis") + 1], "arm64-v8a,armeabi-v7a")
|
|
|
|
def test_lite_single_abi_ignores_and_preserves_previous_artifacts(self):
|
|
self.env["SPOTIFLAC_RUST_ANDROID_ABIS"] = "arm64-v8a"
|
|
output = self.project / "build/app/outputs/flutter-apk"
|
|
output.mkdir(parents=True)
|
|
previous = output / "app-armeabi-v7a-release.apk"
|
|
previous.write_bytes(b"previous build")
|
|
result = self.run_build("--lite")
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
calls = self.calls()
|
|
build = next(call for call in calls if call["args"][:2] == ["build", "apk"])
|
|
self.assertEqual(build["sdk"], "0")
|
|
self.assertNotIn("--lite", build["args"])
|
|
self.assertIn("android-arm64", build["args"])
|
|
audits = [call["args"] for call in calls if call["tool"] == "audit"]
|
|
self.assertEqual(len(audits), 2)
|
|
self.assertTrue(all("--discord-sdk" not in args for args in audits))
|
|
self.assertTrue(all(args[args.index("--abis") + 1] == "arm64-v8a" for args in audits))
|
|
self.assertEqual(previous.read_bytes(), b"previous build")
|
|
|
|
def test_explicit_sdk_disable_is_honored_without_lite_argument(self):
|
|
self.env["SPOTIFLAC_DISCORD_SDK"] = "0"
|
|
self.env["SPOTIFLAC_RUST_ANDROID_ABIS"] = "armeabi-v7a"
|
|
result = self.run_build()
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
audits = [call["args"] for call in self.calls() if call["tool"] == "audit"]
|
|
self.assertEqual(len(audits), 2)
|
|
self.assertTrue(all("--discord-sdk" not in args for args in audits))
|
|
self.assertTrue(all(args[args.index("--abis") + 1] == "armeabi-v7a" for args in audits))
|
|
|
|
def test_fvm_fallback_uses_pinned_version(self):
|
|
self.pinned.unlink()
|
|
self.tool(self.tools / "fvm", FLUTTER_STUB)
|
|
result = self.run_build()
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(self.calls()[0]["tool"], "fvm")
|
|
|
|
def test_production_requires_full_even_with_inherited_sdk_disable(self):
|
|
self.env["SPOTIFLAC_DISCORD_SDK"] = "0"
|
|
result = self.run_build("--production")
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
calls = self.calls()
|
|
build = next(call for call in calls if call["args"][:2] == ["build", "apk"])
|
|
self.assertEqual(build["sdk"], "1")
|
|
self.assertNotIn("--production", build["args"])
|
|
self.assertTrue(all("--discord-sdk" in call["args"] for call in calls if call["tool"] == "audit"))
|
|
|
|
def test_production_rejects_lite_in_either_argument_order(self):
|
|
for arguments in (("--production", "--lite"), ("--lite", "--production")):
|
|
result = self.run_build(*arguments)
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("cannot be combined", result.stderr)
|
|
self.assertFalse(self.log.exists())
|
|
|
|
def test_production_missing_sdk_components_stops_before_flutter(self):
|
|
sdk = self.project / "third_party/spotiflac_discord/sdk"
|
|
for name in (
|
|
"discord_partner_sdk.aar", "notices/Discord-License-Notices.txt",
|
|
"android/prefab/modules/discord_partner_sdk/include/discordpp.h",
|
|
"android/jni/arm64-v8a/libdiscord_partner_sdk.so",
|
|
"android/jni/armeabi-v7a/libdiscord_partner_sdk.so",
|
|
):
|
|
with self.subTest(component=name):
|
|
path = sdk / name
|
|
data = path.read_bytes()
|
|
path.unlink()
|
|
result = self.run_build("--production")
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("production requires", result.stderr)
|
|
path.write_bytes(data)
|
|
self.assertFalse(self.log.exists())
|
|
|
|
def test_wrong_flutter_version_stops_before_build_or_audit(self):
|
|
self.env["BUILD_TEST_FLUTTER_VERSION"] = "0.0.0"
|
|
result = self.run_build()
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("Flutter 3.47.5 is required", result.stderr)
|
|
self.assertEqual(len(self.calls()), 1)
|
|
|
|
def test_invalid_or_overridden_abis_stop_before_flutter(self):
|
|
for abis in ("", "x86_64", "arm64-v8a,arm64-v8a", "armeabi-v7a, arm64-v8a"):
|
|
with self.subTest(abis=abis):
|
|
self.env["SPOTIFLAC_RUST_ANDROID_ABIS"] = abis
|
|
self.assertNotEqual(self.run_build().returncode, 0)
|
|
self.env.pop("SPOTIFLAC_RUST_ANDROID_ABIS")
|
|
self.assertNotEqual(self.run_build("--target-platform=android-x64").returncode, 0)
|
|
self.assertFalse(self.log.exists())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|