1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
"""
Downloads in the Android application, pinned by reading the source.
The page's contract with a native save target is platform.js `nativeSave`: a
sink with write/close/abort, an `open` only when the target can open the file,
and nothing that names a path. The Android sink keeps it; what it may open is
downloads.js `OPENABLE`, held equal here because a second copy of a list of
safe types is how an `.html` gets opened one day.
"""
import re
from pathlib import Path
import pytest
from spa_source import STATIC
PACKAGES = Path(__file__).resolve().parents[2]
MAIN = PACKAGES / "meshbay-android" / "app" / "src" / "main"
SAVE = MAIN / "kotlin" / "org" / "meshbay" / "client" / "save"
SHIM = MAIN / "assets" / "bridge" / "meshbay-bridge.js"
pytestmark = pytest.mark.skipif(not SAVE.exists(), reason="android sources not present")
def _read(path: Path) -> str:
return path.read_text(encoding="utf-8")
def test_what_may_be_opened_is_the_pages_list():
js = _read(STATIC / "downloads.js").split("const OPENABLE = {", 1)[1].split("};", 1)[0]
kt = _read(SAVE / "SaveNames.kt").split("val OPENABLE = mapOf(", 1)[1].split("\n )", 1)[0]
page = {k: v.split(";")[0] for k, v in re.findall(r"(\w+): '([^']+)'", js)}
android = dict(re.findall(r'"(\w+)" to "([^"]+)"', kt))
assert page and android == page, set(android.items()) ^ set(page.items())
def test_open_is_offered_only_where_the_target_says_so():
shim = _read(SHIM)
save = shim.split("saveFile: async", 1)[1].split("\n },", 1)[0]
assert "if (handle.openable) sink.open" in save
sinks = _read(SAVE / "SaveSinks.kt")
assert '.put("openable", SaveNames.openableType(shown) != null)' in sinks
opening = sinks.split("fun open(id: Long)", 1)[1].split("\n }", 1)[0]
assert "SaveNames.openableType(name) ?: throw Refused" in opening
def test_the_page_is_told_names_never_uris():
sinks = _read(SAVE / "SaveSinks.kt")
for fn in ("fun chooseFolder", "fun getFolder", "fun begin"):
body = sinks.split(fn, 1)[1].split("\n fun ", 1)[0]
returned = re.findall(r'put\("(\w+)"', body)
assert not {"uri", "path", "tree"} & set(returned), (fn, returned)
assert "return displayName(treeDocument(tree))" in sinks
def test_the_save_channels_are_the_desktops():
preload = _read(PACKAGES / "meshbay-client" / "src" / "preload.js")
shim = _read(SHIM)
def channels(text: str, call: str) -> set[str]:
return set(re.findall(rf"{call}\('((?:save|folder):[\w:-]+)'", text))
assert channels(shim, "call") == channels(preload, r"ipcRenderer\.invoke")
assert "nativeSave: true" in shim
def test_an_unfinished_file_never_carries_the_final_name():
sinks = _read(SAVE / "SaveSinks.kt")
assert '"$wanted.part"' in sinks
assert "MediaStore.MediaColumns.IS_PENDING, 1" in sinks
assert "MediaStore.MediaColumns.IS_PENDING, 0" in sinks
abort = sinks.split("fun abort(id: Long)", 1)[1].split("\n }", 1)[0]
assert "delete(sink.uri)" in abort
assert "fun cleanUpAfterAKilledProcess" in sinks
assert "saves.cleanUpAfterAKilledProcess()" in _read(
MAIN / "kotlin" / "org" / "meshbay" / "client" / "MainActivity.kt")
def test_a_chosen_folder_that_has_gone_is_not_silently_replaced():
begin = _read(SAVE / "SaveSinks.kt").split("fun begin(", 1)[1].split("\n fun ", 1)[0]
assert "auto && !(configuredTree != null && tree == null)" in begin
def test_writes_are_binary_and_awaited():
shim = _read(SHIM)
assert "head.setUint32(0, 0x4d424231)" in shim
assert "port.postMessage(frame)" in shim
bridge = _read(MAIN / "kotlin" / "org" / "meshbay" / "client" / "bridge" / "Bridge.kt")
before = bridge.split("TYPE_ARRAY_BUFFER", 1)[0]
assert "!isMainFrame" in before, "a binary message must pass the same sender check"
|