Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
import argparse
import errno
import io
import json
import os
import stat
import sys
import tempfile
import unittest
import urllib.error
from unittest import mock
SCRIPTS = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "scripts"))
if SCRIPTS not in sys.path:
sys.path.insert(0, SCRIPTS)
import desk_display
import device
import discover
class DeviceAndCliTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.old_values = (
device.CONFIG_DIR,
device.CONFIG_PATH,
device.PAIRING_PATH,
desk_display.device.CONFIG_DIR,
desk_display.device.CONFIG_PATH,
desk_display.device.PAIRING_PATH,
discover.CONFIG_PATH,
)
config_path = os.path.join(self.temp.name, "autonomous-lcd.json")
pairing_path = os.path.join(self.temp.name, "pairing.json")
device.CONFIG_DIR = self.temp.name
device.CONFIG_PATH = config_path
device.PAIRING_PATH = pairing_path
desk_display.device.CONFIG_DIR = self.temp.name
desk_display.device.CONFIG_PATH = config_path
desk_display.device.PAIRING_PATH = pairing_path
discover.CONFIG_PATH = config_path
def tearDown(self):
(
device.CONFIG_DIR,
device.CONFIG_PATH,
device.PAIRING_PATH,
desk_display.device.CONFIG_DIR,
desk_display.device.CONFIG_PATH,
desk_display.device.PAIRING_PATH,
discover.CONFIG_PATH,
) = self.old_values
self.temp.cleanup()
def test_atomic_config_is_private_and_has_defaults(self):
device.save_config({"devices": []})
mode = stat.S_IMODE(os.stat(device.CONFIG_PATH).st_mode)
self.assertEqual(mode, 0o600)
loaded = device.load_config()
self.assertEqual(loaded["usage_threshold"], 80)
self.assertEqual(loaded["done_cooldown_seconds"], 2)
def test_markdown_is_flattened_and_limited(self):
text = device.strip_markdown("# [Build](https://example.com) `passed` " + "x" * 600)
self.assertFalse(any(mark in text for mark in ("#", "`", "https://")))
self.assertLessEqual(len(text), 500)
self.assertTrue(text.endswith("..."))
@mock.patch("desk_display.device.try_send", return_value=True)
def test_pair_complete_updates_existing_device(self, _send):
device.atomic_write_json(
device.PAIRING_PATH,
{
"created_at": desk_display.time.time(),
"devices": [{"code": "1234", "device_id": "lcd-a1b2c3", "ip": "10.0.0.8"}],
},
)
device.save_config(
{
"devices": [
{
"device_id": "lcd-a1b2c3",
"label": "Old",
"last_known_ip": "10.0.0.2",
}
],
"default_device_id": "lcd-a1b2c3",
}
)
args = argparse.Namespace(code="1234", label="Studio")
self.assertEqual(desk_display.pair_complete(args), 0)
cfg = device.load_config()
self.assertEqual(len(cfg["devices"]), 1)
self.assertEqual(cfg["devices"][0]["label"], "Studio")
self.assertEqual(cfg["devices"][0]["last_known_ip"], "10.0.0.8")
def test_boolean_configuration(self):
args = argparse.Namespace(key="sounds_enabled", value="off")
self.assertEqual(desk_display.configure(args), 0)
self.assertFalse(device.load_config()["sounds_enabled"])
def test_done_cooldown_seconds_configuration(self):
args = argparse.Namespace(key="done_cooldown_seconds", value="15")
self.assertEqual(desk_display.configure(args), 0)
self.assertEqual(device.load_config()["done_cooldown_seconds"], 15)
bad = argparse.Namespace(key="done_cooldown_seconds", value="-1")
self.assertEqual(desk_display.configure(bad), 1)
self.assertEqual(device.load_config()["done_cooldown_seconds"], 15)
def test_layout_validation_clamps_progress_and_text(self):
payload = desk_display._validate_layout(
{
"items": [
{"type": "text", "text": "x" * 120},
{"type": "progress", "value": 130},
]
}
)
self.assertEqual(len(payload["items"][0]["text"]), 95)
self.assertEqual(payload["items"][1]["value"], 100)
self.assertEqual(payload["play_sound"], 20)
def _two_device_cfg(self, ip_a="10.0.0.55", ip_b="10.0.0.6"):
cfg = {
"devices": [
{"device_id": "lcd-a", "label": "A", "last_known_ip": ip_a},
{"device_id": "lcd-b", "label": "B", "last_known_ip": ip_b},
],
"default_device_id": "lcd-a",
}
device.save_config(cfg)
return device.load_config()
def test_send_with_reconnect_does_not_clobber_other_device_ips(self):
cfg = self._two_device_cfg()
device_a = cfg["devices"][0]
def fake_reconnect(device_id):
on_disk = device.load_config()
for dev in on_disk["devices"]:
if dev["device_id"] == "lcd-a":
dev["last_known_ip"] = "10.0.0.55"
elif dev["device_id"] == "lcd-b":
dev["last_known_ip"] = "10.0.0.66"
device.save_config(on_disk)
self.assertEqual(device_id, "lcd-a")
return "10.0.0.55"
with mock.patch.object(device, "try_send", side_effect=[False, True]), mock.patch.object(
discover, "reconnect", side_effect=fake_reconnect
):
self.assertEqual(
device.send_with_reconnect(cfg, device_a, {"text": "hi"}),
"10.0.0.55",
)
saved = {dev["device_id"]: dev["last_known_ip"] for dev in device.load_config()["devices"]}
self.assertEqual(saved["lcd-a"], "10.0.0.55")
self.assertEqual(saved["lcd-b"], "10.0.0.66")
self.assertEqual(cfg["devices"][1]["last_known_ip"], "10.0.0.66")
def test_update_cached_ip_writes_atomically(self):
self._two_device_cfg()
with mock.patch.object(device, "atomic_write_json", wraps=device.atomic_write_json) as writer:
discover._update_cached_ip("lcd-b", "10.0.0.66")
writer.assert_called_once()
self.assertEqual(writer.call_args[0][0], device.CONFIG_PATH)
saved = {dev["device_id"]: dev["last_known_ip"] for dev in device.load_config()["devices"]}
self.assertEqual(saved["lcd-a"], "10.0.0.55")
self.assertEqual(saved["lcd-b"], "10.0.0.66")
mode = stat.S_IMODE(os.stat(device.CONFIG_PATH).st_mode)
self.assertEqual(mode, 0o600)
def test_sandbox_network_error_is_distinguished(self):
wrapped = urllib.error.URLError(OSError(errno.EPERM, "Operation not permitted"))
self.assertTrue(device.is_sandbox_network_error(wrapped))
self.assertTrue(
device.is_sandbox_network_error(OSError(errno.EACCES, "Permission denied"))
)
self.assertFalse(device.is_sandbox_network_error(TimeoutError("timed out")))
self.assertFalse(
device.is_sandbox_network_error(ConnectionRefusedError("refused"))
)
def test_try_send_marks_sandbox_block(self):
blocked = urllib.error.URLError(OSError(errno.EPERM, "Operation not permitted"))
with mock.patch.object(device, "send_to_lcd", side_effect=blocked):
self.assertFalse(device.try_send("10.0.0.55", "lcd-a", {"text": "hi"}))
self.assertTrue(device.last_send_blocked_by_sandbox())
with mock.patch.object(device, "send_to_lcd", side_effect=TimeoutError("timed out")):
self.assertFalse(device.try_send("10.0.0.55", "lcd-a", {"text": "hi"}))
self.assertFalse(device.last_send_blocked_by_sandbox())
def test_notify_sandbox_error_is_not_wifi(self):
device.save_config(
{
"devices": [
{"device_id": "lcd-a", "label": "Desk", "last_known_ip": "10.0.0.55"}
]
}
)
args = argparse.Namespace(
device=None,
message="hi",
size=2,
color="green",
sound=20,
dry_run=False,
)
with mock.patch.object(
desk_display.device, "send_with_reconnect", return_value=None
), mock.patch.object(
desk_display.device, "last_send_blocked_by_sandbox", return_value=True
), mock.patch("sys.stdout", new_callable=io.StringIO) as out:
self.assertEqual(desk_display.notify(args), 1)
text = out.getvalue()
self.assertIn("sandbox", text.lower())
self.assertNotIn(desk_display.WIFI_UNREACHABLE, text)
def test_notify_wifi_error_when_not_sandbox(self):
device.save_config(
{
"devices": [
{"device_id": "lcd-a", "label": "Desk", "last_known_ip": "10.0.0.55"}
]
}
)
args = argparse.Namespace(
device=None,
message="hi",
size=2,
color="green",
sound=20,
dry_run=False,
)
with mock.patch.object(
desk_display.device, "send_with_reconnect", return_value=None
), mock.patch.object(
desk_display.device, "last_send_blocked_by_sandbox", return_value=False
), mock.patch("sys.stdout", new_callable=io.StringIO) as out:
self.assertEqual(desk_display.notify(args), 1)
self.assertIn(desk_display.WIFI_UNREACHABLE, out.getvalue())
if __name__ == "__main__":
unittest.main()
3fa451c16This file is pinned to the selected release. Download the original to open it in your design tool.