70 lines
4.1 KiB
Python
70 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Offline, serialized JVM regressions; uses the existing Gradle Kotlin cache."""
|
|
import argparse
|
|
import fcntl
|
|
import glob
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SRC = ROOT / 'android/app/src/main/kotlin/org/reelbox/reelbox'
|
|
TEST = ROOT / 'android/app/src/test/kotlin/org/reelbox/reelbox'
|
|
|
|
|
|
def jar(group, artifact, version):
|
|
matches = glob.glob(str(Path.home() / '.gradle/caches/modules-2/files-2.1' /
|
|
group / artifact / version / '*' / '*.jar'))
|
|
if len(matches) != 1:
|
|
raise RuntimeError(f'Expected one cached {artifact}:{version}, got {len(matches)}')
|
|
return matches[0]
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--case', default='all')
|
|
parser.add_argument('--skip-integration', action='store_true')
|
|
args = parser.parse_args()
|
|
with (ROOT / '.tooling.lock').open('a') as lock:
|
|
fcntl.flock(lock, fcntl.LOCK_EX)
|
|
helper = SRC / 'RestrictedResourceFetcher.kt'
|
|
assert helper.exists(), 'RM007: no controlled resource fetcher; WebView owns unchecked redirects'
|
|
version = '2.2.21'
|
|
stdlib = jar('org.jetbrains.kotlin', 'kotlin-stdlib', version)
|
|
annotations = jar('org.jetbrains', 'annotations', '13.0')
|
|
compiler = [jar('org.jetbrains.kotlin', item, version) for item in (
|
|
'kotlin-compiler-embeddable', 'kotlin-stdlib', 'kotlin-reflect',
|
|
'kotlin-script-runtime', 'kotlin-daemon-embeddable')]
|
|
compiler += [annotations, jar('org.jetbrains.kotlinx', 'kotlinx-coroutines-core-jvm', '1.8.0')]
|
|
with tempfile.TemporaryDirectory(prefix='native-resource-test-', dir=os.environ.get('TMPDIR')) as out:
|
|
sources = [SRC / 'NativeUrlPolicy.kt', SRC / 'PlaybackSnapshot.kt', helper,
|
|
TEST / 'NativePolicyTest.kt', TEST / 'RestrictedResourceFetchTest.kt']
|
|
subprocess.run(['java', '-Xmx256m', '-XX:MaxMetaspaceSize=192m', '-XX:+UseSerialGC',
|
|
'-cp', os.pathsep.join(compiler), 'org.jetbrains.kotlin.cli.jvm.K2JVMCompiler',
|
|
'-no-stdlib', '-no-reflect', '-jvm-target', '17',
|
|
'-classpath', os.pathsep.join([stdlib, annotations]), '-d', out,
|
|
*map(str, sources)], check=True, cwd=ROOT, timeout=120)
|
|
classpath = os.pathsep.join([out, stdlib])
|
|
subprocess.run(['java', '-Xmx128m', '-cp', classpath,
|
|
'org.reelbox.reelbox.tests.NativePolicyTestKt'], check=True, cwd=ROOT, timeout=60)
|
|
subprocess.run(['java', '-Xmx128m', '--add-modules', 'jdk.httpserver', '-cp', classpath,
|
|
'org.reelbox.reelbox.tests.RestrictedResourceFetchTestKt', args.case], check=True, cwd=ROOT, timeout=60)
|
|
if not args.skip_integration:
|
|
activity = (SRC / 'EmbeddedVideoActivity.kt').read_text()
|
|
start = activity.index('override fun shouldInterceptRequest(')
|
|
end = activity.index('override fun onReceivedSslError', start)
|
|
interceptor = activity[start:end]
|
|
assert 'return null' not in interceptor, 'RM007: interceptor delegates unchecked redirects to WebView'
|
|
assert 'resourceFetcher.fetch(' in interceptor, 'RM007: controlled fetcher is not wired to WebView'
|
|
assert interceptor.count('resourceFetcher.fetch(') == 2, 'Both WebView interceptor overloads must use controlled fetching'
|
|
assert 'request.method, request.requestHeaders' in interceptor, 'Method/range headers are not wired'
|
|
assert 'secureContext = !request.isForMainFrame && securePage' in interceptor, 'Mixed-content guard is missing'
|
|
assert 'handler.cancel()' in activity and 'handler.proceed()' not in activity, 'TLS errors must fail closed'
|
|
assert 'response.body.close()' in activity and 'catch (_: IllegalArgumentException)' in activity, 'Invalid Android response metadata must fail closed'
|
|
print('WebView interceptor source wiring: passed (not a device test)', flush=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|