"""Tests for the graphics engine: coded cells, shader passes, display cache. The load-bearing test here is :meth:`TestDisplayCache.verify_after_every_pass`: every operation writes a coded hypervector *and* a display value, and if those two ever disagree the screen would be showing something the machine does not hold. ``Surface.verify`` decodes real cells and compares, so the cache cannot drift quietly. """ import os import sys import unittest sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from hdc.gfx import SHADERS, Surface, benchmark, value_noise # noqa: E402 D = 2000 def surface(cols=12, rows=4): return Surface(cols, rows, d=D) class TestCodedCells(unittest.TestCase): def test_put_decodes_back_to_the_value_written(self): image = surface() image.put(3, 2, 200) self.assertEqual(image.level_at(3, 2), 200) self.assertEqual(image.shadow[2][3], 200) def test_fill_sets_every_cell_in_the_rectangle(self): image = surface(8, 3) image.fill(2, 1, 4, 2, 90) self.assertEqual(image.level_at(2, 1), 90) self.assertEqual(image.level_at(5, 2), 90) self.assertNotEqual(image.level_at(1, 1), 90) def test_frame_draws_only_the_border(self): image = surface(6, 4) image.frame(0, 0, 6, 4, 240) self.assertEqual(image.level_at(0, 0), 240) self.assertEqual(image.level_at(5, 3), 240) self.assertNotEqual(image.level_at(3, 2), 240) def test_text_sets_levels_and_the_overlay(self): image = surface(10, 2) image.text_at(2, 0, "webOS", 255) self.assertEqual(image.text[0][2:7], ["w", "e", "b", "O", "S"]) self.assertEqual(image.level_at(2, 0), 255) self.assertIn("webOS", image.rows()[0]) class TestDisplayCache(unittest.TestCase): def assertVerified(self, image): result = image.verify() self.assertTrue(result["ok"], msg="cache drifted: %s" % (result,)) self.assertGreater(result["checked"], 0) def test_verify_after_primitives(self): image = surface(10, 5) self.assertVerified(image) image.fill(1, 1, 4, 3, 77) self.assertVerified(image) image.frame(0, 0, 10, 5, 200) self.assertVerified(image) image.text_at(1, 1, "hi", 120) self.assertVerified(image) def test_verify_after_every_shader(self): for name in SHADERS: with self.subTest(shader=name): self.assertVerified(surface(16, 6).apply(name)) def test_verify_after_each_field_operation(self): image = surface(14, 5) image.gradient(top=10, bottom=200, vertical=True) self.assertVerified(image) image.noise(scale=3, octaves=2, seed=2, amplitude=80) self.assertVerified(image) image.max_blend(scale=4, seed=4, amplitude=60) self.assertVerified(image) image.edges(mode="proxy", gain=2) self.assertVerified(image) def test_verify_after_vignette_and_scanline(self): image = surface(12, 6).apply("background") self.assertVerified(image) image.scanline(steps=1) self.assertVerified(image) class TestExactArithmetic(unittest.TestCase): def test_dim_halves_exactly(self): image = surface(4, 1) image.put(0, 0, 128) image.put(1, 0, 127) image.dim_region(1) self.assertEqual(image.level_at(0, 0), 64) self.assertEqual(image.level_at(1, 0), 63) def test_dim_twice_quarters(self): image = surface(2, 1) image.put(0, 0, 200) image.dim_region(2) self.assertEqual(image.level_at(0, 0), 50) def test_brighten_doubles(self): image = surface(2, 1) image.put(0, 0, 60) image.brighten_region(1) self.assertEqual(image.level_at(0, 0), 120) def test_scanline_dims_only_alternate_rows(self): image = surface(6, 4) image.fill(0, 0, 6, 4, 128) image.scanline(steps=1, offset=1) self.assertEqual(image.level_at(0, 0), 128) # untouched row self.assertEqual(image.level_at(0, 1), 64) # dimmed row self.assertEqual(image.level_at(0, 2), 128) self.assertEqual(image.level_at(0, 3), 64) class TestEdges(unittest.TestCase): def test_proxy_edges_peak_at_a_step_boundary(self): image = surface(12, 1) image.fill(0, 0, 6, 1, 20) image.fill(6, 0, 6, 1, 220) image.edges(mode="proxy", gain=2) boundary = image.level_at(5, 0) interior = image.level_at(2, 0) self.assertGreater(boundary, interior) self.assertEqual(interior, 0) # identical neighbours: no edge def test_exact_edges_equal_the_difference(self): image = surface(8, 1) image.fill(0, 0, 4, 1, 10) image.fill(4, 0, 4, 1, 40) image.edges(mode="exact") self.assertEqual(image.level_at(3, 0), 30) # |10 - 40| self.assertEqual(image.level_at(0, 0), 0) # |10 - 10| def test_bad_mode_raises(self): with self.assertRaises(ValueError): surface(4, 2).edges(mode="bogus") class TestSurfaceOutput(unittest.TestCase): def test_gradient_is_monotonic_down_the_column(self): image = surface(3, 10) image.gradient(top=0, bottom=250, vertical=True) column = [image.level_at(0, y) for y in range(10)] self.assertEqual(column, sorted(column)) self.assertEqual(column[0], 0) self.assertEqual(column[-1], 250) def test_rows_are_exactly_rows_long_and_never_wider_than_cols(self): image = surface(15, 6).apply("plasma") rows = image.rows() self.assertEqual(len(rows), 6) for row in rows: self.assertLessEqual(len(row), 15) def test_ascii_joins_the_rows(self): image = surface(5, 3).apply("flat") self.assertEqual(image.ascii().count("\n"), 2) def test_out_of_bounds_writes_are_clipped_not_raised(self): image = surface(6, 3) image.fill(-4, -4, 5, 5, 200) # mostly outside image.text_at(4, 0, "abcdef", 240) # runs past the right edge image.put(99, 99, 255) # entirely outside self.assertEqual(image.text[0][4], "a") self.assertEqual(image.text[0][5], "b") self.assertTrue(image.verify()["ok"]) def test_unknown_shader_raises(self): with self.assertRaises(KeyError): surface(4, 2).apply("nope") def test_empty_surface_is_rejected(self): for args in ((0, 5), (5, 0), (-1, 3)): with self.subTest(args=args): with self.assertRaises(ValueError): Surface(*args, d=D) class TestNoise(unittest.TestCase): def test_value_noise_is_bounded_and_not_constant(self): field = value_noise(16, 8, 4, seed=3, amplitude=100) flat = [value for row in field for value in row] self.assertEqual(len(flat), 16 * 8) self.assertTrue(all(0 <= value <= 100 for value in flat)) self.assertGreater(len(set(flat)), 1) def test_noise_is_deterministic_for_a_seed(self): first = value_noise(8, 4, 2, seed=9, amplitude=50) second = value_noise(8, 4, 2, seed=9, amplitude=50) self.assertEqual(first, second) def test_noise_changes_with_the_seed(self): first = value_noise(8, 4, 2, seed=9, amplitude=50) second = value_noise(8, 4, 2, seed=10, amplitude=50) self.assertNotEqual(first, second) class TestBenchmark(unittest.TestCase): def test_benchmark_covers_every_shader(self): stats = benchmark(d=D, cols=20, rows=8) self.assertEqual(set(stats["shaders"]), set(SHADERS)) for name, ms in stats["shaders"].items(): self.assertGreater(ms, 0.0, msg=name) self.assertGreater(stats["exact_edges_ms_per_128_cells"], 0.0) self.assertEqual(stats["cells"], 160) if __name__ == "__main__": unittest.main()