"""The webOS: window manager, apps, filesystem wiring, and the memory map. Each test either reads a desktop that nothing mutates (built once per class) or builds its own, because the window manager is stateful and a shared desktop would make the tests order-dependent. ``d=2000`` throughout: it is the codec floor, and the desktop renders a full 80x30 shader frame per call. """ import unittest from hdc.gfx import SHADERS from hdc.os import APPS, COLS, ROWS, Desktop, MemoryMap, boot, tour class ReadOnlyDesktop(unittest.TestCase): """A started desktop shared by the tests that never mutate it.""" @classmethod def setUpClass(cls): cls.desktop = Desktop(d=2000).start() def test_start_opens_the_tiled_session(self): desktop = Desktop(d=2000).start() self.assertEqual([w.app for w in desktop.windows], ["terminal", "monitor", "files"]) self.assertEqual(desktop.windows[desktop.focus].app, "terminal") def test_start_is_idempotent(self): desktop = Desktop(d=2000) desktop.start() before = len(desktop.windows) desktop.start() self.assertEqual(len(desktop.windows), before) def test_launching_an_open_app_raises_it_instead_of_duplicating(self): desktop = Desktop(d=2000).start() desktop.launch("files") desktop.launch("files") self.assertEqual(sum(1 for w in desktop.windows if w.app == "files"), 1) self.assertEqual(desktop.windows[desktop.focus].app, "files") def test_close_removes_the_focused_window(self): # a fresh desktop: closing mutates the session, and the class-level one # is shared with the frame test below desktop = Desktop(d=2000).start() before = len(desktop.windows) focused = desktop.focused() self.assertTrue(desktop.close()) self.assertEqual(len(desktop.windows), before - 1) self.assertNotIn(focused, desktop.windows) def test_frame_has_the_grid_shape_and_a_menu_bar(self): frame = self.desktop.frame() self.assertEqual(len(frame), ROWS) for row in frame: self.assertLessEqual(len(row), COLS) text = "\n".join(frame) self.assertIn("webOS", frame[0]) for key in ("terminal", "monitor", "shaders"): self.assertIn(key, frame[0]) # the taskbar names the open windows self.assertIn("[Terminal]", frame[-1]) self.assertGreater(self.desktop.last_frame_ms, 0.0) def test_memory_counts_the_filesystem_cells(self): """The filesystem writes into the machine's storage, not its own. This is the bug the coordinator fixed: two stores made every free-cell figure a lie, so the counts here are pinned. """ desktop = self.desktop buckets = desktop.memory.buckets() self.assertIn("fs", buckets) self.assertEqual(buckets["fs"], len(desktop.fs.nodes)) self.assertEqual(desktop.memory.stat()["cells"], len(desktop.kernel.storage)) def test_memory_report_and_state_shape(self): report = self.desktop.memory.report() self.assertIn("cells", report) state = self.desktop.state() for key in ("frame", "windows", "memory", "fs", "status", "apps"): self.assertIn(key, state) self.assertEqual(len(state["frame"]), ROWS) self.assertIn("webOS", self.desktop.report()) class TestMemoryAllocator(unittest.TestCase): def setUp(self): self.desktop = Desktop(d=2000) self.map = self.desktop.memory def test_allocate_and_free(self): before = self.map.stat()["cells"] names = self.map.allocate("scratch", 4) self.assertEqual(len(names), 4) self.assertEqual(self.map.stat()["cells"], before + 4) self.assertEqual(self.map.buckets().get("mem"), 4) self.assertEqual(self.map.free("scratch"), 4) self.assertEqual(self.map.stat()["cells"], before) def test_free_unknown_tag_is_zero(self): self.assertEqual(self.map.free("never-allocated"), 0) def test_allocate_zero_is_empty(self): self.assertEqual(self.map.allocate("nothing", 0), []) class TestTerminalApp(unittest.TestCase): def setUp(self): self.desktop = Desktop(d=2000).start() self.terminal = self.desktop.windows[0] self.desktop.focus = 0 def test_typing_then_enter_runs_the_machine(self): self.desktop.text("stat") self.assertEqual(self.terminal.state["typing"], "stat") result = self.desktop.key("Enter") self.assertEqual(result["status"], "kernel: stat") buffer = "\n".join(self.terminal.state["buffer"]) self.assertIn("cells=", buffer) self.assertEqual(self.terminal.state["typing"], "") def test_backspace_edits_the_typing_buffer(self): self.desktop.text("stad") self.desktop.key("Backspace") self.assertEqual(self.terminal.state["typing"], "sta") def test_empty_enter_does_not_run_anything(self): result = self.desktop.key("Enter") self.assertEqual(result["action"], "key") self.assertEqual(self.terminal.state["typing"], "") class TestFilesApp(unittest.TestCase): def setUp(self): self.desktop = Desktop(d=2000).start() self.desktop.key("F2") self.window = self.desktop.focused() # entries are populated by render(), which the frame does self.desktop.frame() self.assertEqual(self.window.app, "files") def test_enter_opens_a_directory_and_u_goes_back_up(self): self.assertEqual(self.window.state["cwd"], "/home/user") self.desktop.key("Enter") # cursor starts on img/ self.assertEqual(self.window.state["cwd"], "/home/user/img") self.desktop.key("u") self.assertEqual(self.window.state["cwd"], "/home/user") def test_enter_on_a_file_opens_the_editor(self): self.desktop.key("ArrowDown") # img/ -> src/ self.desktop.key("ArrowDown") # src/ -> README.txt self.desktop.key("Enter") editor = self.desktop.focused() self.assertEqual(editor.app, "editor") self.assertTrue(editor.state["path"].endswith("README.txt")) def test_cursor_stays_inside_the_listing(self): for _ in range(20): self.desktop.key("ArrowDown") entries = self.window.state["entries"] self.assertLessEqual(self.window.state["cursor"], len(entries) - 1) class TestEditorApp(unittest.TestCase): def test_appending_reaches_the_filesystem(self): desktop = Desktop(d=2000).start() path = "/home/user/README.txt" window = desktop.open_file(path) self.assertEqual(window.app, "editor") desktop.text("hello line") result = desktop.key("Enter") self.assertEqual(result["status"], "appended to " + path) self.assertIn("hello line", desktop.fs.read(path)) self.assertEqual(window.state["typing"], "") def test_editor_without_a_file_says_so(self): desktop = Desktop(d=2000).start() window = desktop.launch("editor") desktop.frame() app = window.state["app"] self.assertIn("no file open", "\n".join(app.render(desktop, window))) class TestShaderApp(unittest.TestCase): def setUp(self): self.desktop = Desktop(d=2000).start() self.desktop.key("F5") self.window = self.desktop.focused() self.desktop.frame() # render() picks the default def test_space_cycles_the_shader(self): first = self.window.state["shader"] self.assertIn(first, SHADERS) self.desktop.key(" ") second = self.window.state["shader"] self.assertIn(second, SHADERS) self.assertNotEqual(first, second) def test_e_toggles_the_edge_pass(self): self.assertFalse(self.window.state.get("edges")) self.desktop.key("e") self.assertEqual(self.window.state["edges"], "proxy") self.desktop.key("e") self.assertFalse(self.window.state.get("edges")) def test_the_window_holds_a_rendered_surface(self): surface = self.window.state["frame"] self.assertEqual(len(surface.rows()), self.window.inner_h - 2) self.assertEqual(len(surface.rows()[0]) <= self.window.inner_w, True) class TestKeyboardRouting(unittest.TestCase): def test_function_keys_launch_every_app(self): desktop = Desktop(d=2000) for key, app in Desktop.FUNCTION_KEYS.items(): result = desktop.key(key) self.assertEqual(result["action"], "launch") self.assertIsNotNone(desktop.find(app), msg=app) self.assertEqual(len(desktop.windows), len(APPS)) def test_tab_cycles_focus(self): desktop = Desktop(d=2000).start() desktop.focus = 0 desktop.key("Tab") self.assertEqual(desktop.focus, 1) desktop.key("Ctrl+Tab") self.assertEqual(desktop.focus, 0) def test_ctrl_w_closes_and_ctrl_right_moves(self): desktop = Desktop(d=2000).start() before = len(desktop.windows) desktop.key("Ctrl+W") self.assertEqual(len(desktop.windows), before - 1) desktop = Desktop(d=2000).start() window = desktop.focused() start_x = window.x result = desktop.key("Ctrl+Right") self.assertEqual(result["action"], "move") self.assertEqual(window.x, start_x + 3) def test_key_with_no_window_is_not_an_exception(self): desktop = Desktop(d=2000) self.assertEqual(desktop.key("q")["action"], "none") self.assertEqual(desktop.text("x")["action"], "none") def test_unknown_app_raises(self): with self.assertRaises(KeyError): Desktop(d=2000).launch("spreadsheet") class TestClickFocus(unittest.TestCase): def test_click_focuses_the_window_under_the_cell(self): desktop = Desktop(d=2000) terminal = desktop.launch("terminal", 1, 1) monitor = desktop.launch("monitor", 50, 1) self.assertEqual(desktop.focused(), monitor) desktop.click(2, 2) self.assertEqual(desktop.focused(), terminal) desktop.click(60, 2) self.assertEqual(desktop.focused(), monitor) def test_click_on_empty_desktop_keeps_focus(self): desktop = Desktop(d=2000).start() focused = desktop.focused() self.assertEqual(desktop.click(0, ROWS - 1), "") self.assertEqual(desktop.focused(), focused) class TestSession(unittest.TestCase): def test_boot_returns_a_started_desktop(self): desktop = boot(2000) self.assertEqual(len(desktop.windows), 3) self.assertEqual(desktop.windows[0].app, "terminal") def test_tour_prints_a_frame_and_the_report(self): text = tour(2000) self.assertIn("=== frame after tour ===", text) self.assertIn("webOS:", text) self.assertIn("memory:", text) class TestMemoryMapStandalone(unittest.TestCase): def test_buckets_group_by_prefix(self): desktop = Desktop(d=2000) map_ = MemoryMap(desktop.kernel.storage) desktop.kernel.storage.write("code/0", 0) buckets = map_.buckets() self.assertIn("code", buckets) self.assertIn("fs", buckets) self.assertEqual(buckets["code"], 1) if __name__ == "__main__": unittest.main()