mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-09-19 04:59:59 +00:00
Fix phone-only Mesh Lab scenario selection
This commit is contained in:
parent
67e942b04b
commit
2c59c49f72
@ -298,7 +298,7 @@ python3 tools/release_gate/mesh_lab.py scenario all \
|
|||||||
| `dm` | Noise handshake both ways, encrypted DM round trips with content match |
|
| `dm` | Noise handshake both ways, encrypted DM round trips with content match |
|
||||||
| `favorite_verification` | favorite signal, orange-outline/filled mutual state, and peer fingerprint verification |
|
| `favorite_verification` | favorite signal, orange-outline/filled mutual state, and peer fingerprint verification |
|
||||||
| `broadcast` | public mesh message A→B |
|
| `broadcast` | public mesh message A→B |
|
||||||
| `watch_power` | phone→Watch screen-off delivery, two-link ceiling, scan quiescence, and zero background RSSI polling |
|
| `watch_power` | phone→Watch screen-off delivery, two-link ceiling, scan quiescence, and zero background RSSI polling (Watch topology only) |
|
||||||
| `ptt_dm` | Noise-encrypted 440 Hz PTT in both directions; asserts real-time capture, zero sequence gaps, decoded PCM duration/energy/continuity, and finalized-note absorption |
|
| `ptt_dm` | Noise-encrypted 440 Hz PTT in both directions; asserts real-time capture, zero sequence gaps, decoded PCM duration/energy/continuity, and finalized-note absorption |
|
||||||
| `ptt_broadcast` | signed public 440 Hz PTT with the same bidirectional packet and decoded-audio quality assertions |
|
| `ptt_broadcast` | signed public 440 Hz PTT with the same bidirectional packet and decoded-audio quality assertions |
|
||||||
| `file` | 1 KB broadcast file, receiver SHA-256 matches fixture |
|
| `file` | 1 KB broadcast file, receiver SHA-256 matches fixture |
|
||||||
@ -308,7 +308,7 @@ python3 tools/release_gate/mesh_lab.py scenario all \
|
|||||||
| `raw` | raw packet injection is accepted by the mesh |
|
| `raw` | raw packet injection is accepted by the mesh |
|
||||||
| `session_recovery` | force-stop B mid-session: identity persists, re-handshake, DMs flow again |
|
| `session_recovery` | force-stop B mid-session: identity persists, re-handshake, DMs flow again |
|
||||||
| `identity_reset` | pm clear B mid-session: new identity, rediscovery, handshake, DMs |
|
| `identity_reset` | pm clear B mid-session: new identity, rediscovery, handshake, DMs |
|
||||||
| `all` | every scenario above in sequence |
|
| `all` | every scenario supported by the selected topology in sequence; phone→phone excludes Watch-only checks |
|
||||||
|
|
||||||
Each run writes `<scenario>-evidence.json` to `--out` (digests, timings,
|
Each run writes `<scenario>-evidence.json` to `--out` (digests, timings,
|
||||||
session states, logcat excerpts on failure) and exits non-zero on failure.
|
session states, logcat excerpts on failure) and exits non-zero on failure.
|
||||||
|
|||||||
@ -964,9 +964,12 @@ SCENARIOS = {
|
|||||||
"identity_reset": scenario_identity_reset,
|
"identity_reset": scenario_identity_reset,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WATCH_ONLY_SCENARIOS = frozenset({"watch_power"})
|
||||||
|
PHONE_SCENARIOS = tuple(name for name in SCENARIOS if name not in WATCH_ONLY_SCENARIOS)
|
||||||
|
|
||||||
# Scenarios supported when device B is a watch (file scenarios are receive-only: phone sends,
|
# Scenarios supported when device B is a watch (file scenarios are receive-only: phone sends,
|
||||||
# the watch must receive with matching digests).
|
# the watch must receive with matching digests).
|
||||||
WATCH_SCENARIOS = [
|
WATCH_SCENARIOS = (
|
||||||
"dm",
|
"dm",
|
||||||
"favorite_verification",
|
"favorite_verification",
|
||||||
"broadcast",
|
"broadcast",
|
||||||
@ -978,14 +981,14 @@ WATCH_SCENARIOS = [
|
|||||||
"file_private",
|
"file_private",
|
||||||
"session_recovery",
|
"session_recovery",
|
||||||
"identity_reset",
|
"identity_reset",
|
||||||
]
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_scenario(name: str, a: Device, b: Device, out: Path | None) -> dict:
|
def run_scenario(name: str, a: Device, b: Device, out: Path | None) -> dict:
|
||||||
started = time.time()
|
started = time.time()
|
||||||
evidence: dict[str, object] = {"scenario": name, "devices": [a.alias, b.alias]}
|
evidence: dict[str, object] = {"scenario": name, "devices": [a.alias, b.alias]}
|
||||||
try:
|
try:
|
||||||
supported = WATCH_SCENARIOS if isinstance(b, WatchDevice) else list(SCENARIOS)
|
supported = WATCH_SCENARIOS if isinstance(b, WatchDevice) else PHONE_SCENARIOS
|
||||||
if name == "all":
|
if name == "all":
|
||||||
results = {}
|
results = {}
|
||||||
failures = []
|
failures = []
|
||||||
|
|||||||
40
tools/release_gate/test_mesh_lab.py
Normal file
40
tools/release_gate/test_mesh_lab.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import unittest
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from tools.release_gate import mesh_lab
|
||||||
|
|
||||||
|
|
||||||
|
class MeshLabScenarioDispatchTest(unittest.TestCase):
|
||||||
|
def scenario_handlers(self):
|
||||||
|
return {
|
||||||
|
name: mock.Mock(return_value={"scenario": name})
|
||||||
|
for name in mesh_lab.SCENARIOS
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_phone_all_excludes_watch_only_scenarios(self):
|
||||||
|
handlers = self.scenario_handlers()
|
||||||
|
phone_a = mesh_lab.Device("phone-a", "alpha")
|
||||||
|
phone_b = mesh_lab.Device("phone-b", "beta")
|
||||||
|
|
||||||
|
with mock.patch.object(mesh_lab, "SCENARIOS", handlers):
|
||||||
|
result = mesh_lab.run_scenario("all", phone_a, phone_b, out=None)
|
||||||
|
|
||||||
|
self.assertEqual("pass", result["status"])
|
||||||
|
handlers["watch_power"].assert_not_called()
|
||||||
|
for name in mesh_lab.PHONE_SCENARIOS:
|
||||||
|
handlers[name].assert_called_once_with(phone_a, phone_b)
|
||||||
|
|
||||||
|
def test_watch_all_includes_watch_power(self):
|
||||||
|
handlers = self.scenario_handlers()
|
||||||
|
phone = mesh_lab.Device("phone", "alpha")
|
||||||
|
watch = mesh_lab.WatchDevice("watch")
|
||||||
|
|
||||||
|
with mock.patch.object(mesh_lab, "SCENARIOS", handlers):
|
||||||
|
result = mesh_lab.run_scenario("all", phone, watch, out=None)
|
||||||
|
|
||||||
|
self.assertEqual("pass", result["status"])
|
||||||
|
handlers["watch_power"].assert_called_once_with(phone, watch)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Loading…
x
Reference in New Issue
Block a user