From aed32f20625a6206628b577d743d96552f81e91a Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 10 Oct 2026 14:40:05 +0200 Subject: feat(android): back text messages up, in a build Play does not get A Messages section sends the SMS added since the last copy, as restorable XML, into /-messages/YYYY. A play flavor has neither READ_SMS nor the code that reads messages; full is the default. Co-Authored-By: Claude Opus 5.5 --- packages/meshbay-hub/tests/test_android_shell.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'packages/meshbay-hub/tests/test_android_shell.py') diff --git a/packages/meshbay-hub/tests/test_android_shell.py b/packages/meshbay-hub/tests/test_android_shell.py index 426b560..7b2e79f 100644 --- a/packages/meshbay-hub/tests/test_android_shell.py +++ b/packages/meshbay-hub/tests/test_android_shell.py @@ -147,7 +147,8 @@ def test_the_shim_offers_desktop_channels_and_native_answers_each(): # A phone has a push distributor to talk to and a camera roll and an # address book to back up, and a desktop has none of them; those families are the ones the desktop lacks # rather than the ones it shares. - phone_only = {c for c in shim if c.startswith(("push:", "photosync:", "phonesync:", "contactsync:"))} + phone_only = {c for c in shim if c.startswith(("push:", "photosync:", "phonesync:", "contactsync:", + "messagesync:"))} assert any(c.startswith("push:") for c in phone_only), "the push channels are gone" assert any(c.startswith("photosync:") for c in phone_only), "the backup channels are gone" assert shim - phone_only <= preload, f"channels the desktop does not have: {shim - preload}" @@ -255,13 +256,29 @@ def test_a_release_is_signed_with_the_release_key_or_not_built(): assert 'signingConfigs.getByName("debug")' not in build assert 'signingConfigs.findByName("release")' in build assert 'providers.gradleProperty("meshbayReleaseStorePassword")' in build - assert '"preReleaseBuild"' in build and "throw GradleException" in build + assert 'name.endsWith("ReleaseBuild")' in build and "throw GradleException" in build assert not re.search(r'storePassword = "', build) +def test_the_play_build_cannot_read_text_messages(): + """Play's policy keeps READ_SMS for the default SMS application: the Play + build has neither the permission nor the code that reads messages.""" + main = _read(APP / "src" / "main" / "AndroidManifest.xml") + assert "READ_SMS" not in main + assert "READ_SMS" in _read(APP / "src" / "full" / "AndroidManifest.xml") + assert not (APP / "src" / "play" / "AndroidManifest.xml").exists() or \ + "READ_SMS" not in _read(APP / "src" / "play" / "AndroidManifest.xml") + play = list((APP / "src" / "play").rglob("*.kt")) + assert play and all("Telephony" not in _read(f) and "SmsSource" not in _read(f) for f in play) + assert not list((APP / "src" / "main").rglob("SmsSource.kt")) + + @pytest.mark.skipif(not os.environ.get("ANDROID_HOME") or shutil.which("java") is None, reason="no Android SDK in the environment") def test_the_jvm_unit_tests_pass(): - result = subprocess.run(["./gradlew", "--no-daemon", "-q", "testDebugUnitTest"], + # The tests are shared; the Play build is compiled too, so a flavor file + # missing from it fails here rather than at release time. + result = subprocess.run(["./gradlew", "--no-daemon", "-q", "testFullDebugUnitTest", + "compilePlayDebugKotlin"], cwd=ANDROID, capture_output=True, text=True, timeout=900) assert result.returncode == 0, result.stdout[-3000:] + result.stderr[-3000:] -- cgit v1.2.3