163 lines
5.5 KiB
Python
163 lines
5.5 KiB
Python
"""Tests for textgrid color packing (no GPU required)."""
|
|
|
|
from textgrid._pack_style import pack_style_colors, _pack_one, _xterm
|
|
|
|
|
|
def test_pack_red():
|
|
"""(255, 0, 0) → 0xFF000000 (R in bits 31-24)"""
|
|
from termstr import CharStyle
|
|
result = pack_style_colors((CharStyle(fg_color=(255, 0, 0)),))
|
|
assert result[0] == 0xFF000000
|
|
|
|
|
|
def test_pack_green():
|
|
"""(0, 255, 0) → 0x00FF0000 (G in bits 23-16)"""
|
|
from termstr import CharStyle
|
|
result = pack_style_colors((CharStyle(fg_color=(0, 255, 0)),))
|
|
assert result[0] == 0x00FF0000
|
|
|
|
|
|
def test_pack_blue():
|
|
"""(0, 0, 255) → 0x0000FF00 (B in bits 15-8)"""
|
|
from termstr import CharStyle
|
|
result = pack_style_colors((CharStyle(fg_color=(0, 0, 255)),))
|
|
assert result[0] == 0x0000FF00
|
|
|
|
|
|
def test_pack_black():
|
|
"""(0, 0, 0) → 0x00000000"""
|
|
from termstr import CharStyle
|
|
result = pack_style_colors((CharStyle(fg_color=(0, 0, 0)),))
|
|
assert result[0] == 0x00000000
|
|
|
|
|
|
def test_pack_white():
|
|
"""(255, 255, 255) → 0xFFFFFF00"""
|
|
from termstr import CharStyle
|
|
result = pack_style_colors((CharStyle(fg_color=(255, 255, 255)),))
|
|
assert result[0] == 0xFFFFFF00
|
|
|
|
|
|
def test_pack_fg_and_bg():
|
|
"""fg and bg are interleaved in the output array"""
|
|
from termstr import CharStyle
|
|
result = pack_style_colors((CharStyle(fg_color=(255, 0, 0), bg_color=(0, 0, 255)),))
|
|
assert result[0] == 0xFF000000, "fg should be first"
|
|
assert result[1] == 0x0000FF00, "bg should be second"
|
|
assert result[2] == 0, "attr should be 0 for default style"
|
|
|
|
|
|
def test_pack_xterm_index_9():
|
|
"""xterm index 9 is bright red = (255, 0, 0)"""
|
|
from termstr import CharStyle
|
|
result = pack_style_colors((CharStyle(fg_color=9),))
|
|
expected = pack_style_colors((CharStyle(fg_color=(255, 0, 0)),))
|
|
assert result[0] == expected[0], "index 9 should match (255, 0, 0)"
|
|
|
|
|
|
def test_xterm_table_index_0():
|
|
"""xterm index 0 is (0, 0, 0)"""
|
|
assert _xterm[0] == (0, 0, 0)
|
|
|
|
|
|
def test_xterm_table_index_1():
|
|
"""xterm index 1 is (205, 0, 0)"""
|
|
assert _xterm[1] == (205, 0, 0)
|
|
|
|
|
|
def test_xterm_table_index_15():
|
|
"""xterm index 15 is (255, 255, 255)"""
|
|
assert _xterm[15] == (255, 255, 255)
|
|
|
|
|
|
def test_xterm_table_index_16():
|
|
"""xterm index 16 is (0, 0, 0) — start of color cube"""
|
|
assert _xterm[16] == (0, 0, 0)
|
|
|
|
|
|
def test_xterm_table_index_231():
|
|
"""xterm index 231 is (255, 255, 255) — end of color cube"""
|
|
assert _xterm[231] == (255, 255, 255)
|
|
|
|
|
|
def test_xterm_table_index_232():
|
|
"""xterm index 232 is (8, 8, 8) — start of gray ramp"""
|
|
assert _xterm[232] == (8, 8, 8)
|
|
|
|
|
|
def test_xterm_table_index_255():
|
|
"""xterm index 255 is (238, 238, 238) — end of gray ramp"""
|
|
assert _xterm[255] == (238, 238, 238)
|
|
|
|
|
|
def test_identity_fast_path_matches_slow_path():
|
|
"""all(s is first) fast path produces same output as per-element iteration"""
|
|
from termstr import CharStyle
|
|
style = CharStyle(fg_color=(255, 80, 80), bg_color=(20, 40, 60))
|
|
styles = tuple([style] * 100)
|
|
# The identity check will trigger for n > 1
|
|
result = pack_style_colors(styles)
|
|
# Length: 100 chars * 3 values (fg, bg, attr) = 300
|
|
assert len(result) == 300
|
|
# Every triplet should be identical
|
|
for i in range(0, 300, 3):
|
|
assert result[i] == result[0], f"fg differs at char {i//3}"
|
|
assert result[i + 1] == result[1], f"bg differs at char {i//3}"
|
|
assert result[i + 2] == result[2], f"attr differs at char {i//3}"
|
|
|
|
|
|
def test_mixed_styles_are_all_different():
|
|
"""Each char has different colors — no identity optimization triggered"""
|
|
from termstr import CharStyle
|
|
styles = tuple([
|
|
CharStyle(fg_color=(255, 0, 0)),
|
|
CharStyle(fg_color=(0, 255, 0)),
|
|
CharStyle(fg_color=(0, 0, 255)),
|
|
])
|
|
result = pack_style_colors(styles)
|
|
assert len(result) == 9
|
|
assert result[0] != result[3], "red != green"
|
|
assert result[0] != result[6], "red != blue"
|
|
assert result[3] != result[6], "green != blue"
|
|
|
|
|
|
def test_output_length():
|
|
"""N chars produces 3N output values"""
|
|
from termstr import CharStyle
|
|
for n in [1, 5, 100]:
|
|
styles = tuple([CharStyle(fg_color=(255, 0, 0))] * n)
|
|
result = pack_style_colors(styles)
|
|
assert len(result) == 3 * n, f"expected {3*n}, got {len(result)}"
|
|
|
|
|
|
def test_xterm_pack_matches_rgb():
|
|
"""Packing xterm index should produce same u32 as direct RGB"""
|
|
from termstr import CharStyle
|
|
for idx in [1, 9, 16, 100, 200, 255]:
|
|
r, g, b = _xterm[idx]
|
|
xterm_result = pack_style_colors((CharStyle(fg_color=idx),))
|
|
rgb_result = pack_style_colors((CharStyle(fg_color=(r, g, b)),))
|
|
assert xterm_result[0] == rgb_result[0], \
|
|
f"index {idx} = ({r},{g},{b}) didn't match direct RGB"
|
|
|
|
|
|
def test_attr_encoding():
|
|
"""bold/italic flags encoded in attr byte"""
|
|
from termstr import CharStyle
|
|
r = pack_style_colors((CharStyle(fg_color=(255, 0, 0)),))
|
|
assert r[2] == 0, "default: no bold, no italic"
|
|
|
|
r = pack_style_colors((CharStyle(fg_color=(255, 0, 0)).bold(),))
|
|
assert r[2] & 1, "bold bit set"
|
|
|
|
r = pack_style_colors((CharStyle(fg_color=(255, 0, 0)).italic(),))
|
|
assert r[2] & 2, "italic bit set"
|
|
|
|
r = pack_style_colors((CharStyle(fg_color=(255, 0, 0)).bold().italic(),))
|
|
assert (r[2] & 3) == 3, "both bold and italic bits set"
|
|
|
|
r = pack_style_colors((CharStyle(fg_color=(255, 0, 0)).underline(),))
|
|
assert r[2] & 4, "underline bit set"
|
|
|
|
r = pack_style_colors((CharStyle(fg_color=(255, 0, 0)).bold().italic().underline(),))
|
|
assert (r[2] & 7) == 7, "bold, italic, and underline bits set"
|