@@ -4,6 +4,115 @@ import kotlin.test.*
44
55class BitPackingTest {
66
7+ @Test
8+ fun `packFlags simple bit pattern` () {
9+ val flags = booleanArrayOf(true , false , true )
10+ val packed = PackedUtils .packFlags(flags)
11+
12+ assertEquals(1 , packed.size, " Should pack into 1 byte" )
13+ assertEquals(5 .toByte(), packed[0 ], " Bits should match 101 binary" )
14+ }
15+
16+ @Test
17+ fun `packFlags multi byte` () {
18+ val flags = BooleanArray (16 )
19+ flags[0 ] = true
20+ flags[10 ] = true
21+
22+ val packed = PackedUtils .packFlags(flags)
23+
24+ assertEquals(2 , packed.size, " Should require 2 bytes" )
25+ assertEquals(1 .toByte(), packed[0 ], " Byte 0 should have bit 0 set" )
26+ assertEquals(4 .toByte(), packed[1 ], " Byte 1 should have bit 2 set (index 10)" )
27+ }
28+
29+ @Test
30+ fun `packFlags all false optimizes to empty` () {
31+ val flags = booleanArrayOf(false , false , false , false )
32+ val packed = PackedUtils .packFlags(flags)
33+
34+ assertEquals(0 , packed.size, " All false should result in 0 bytes" )
35+ }
36+
37+ @Test
38+ fun `packFlags empty input` () {
39+ val flags = BooleanArray (0 )
40+ val packed = PackedUtils .packFlags(flags)
41+
42+ assertEquals(0 , packed.size)
43+ }
44+
45+ @Test
46+ fun `unpackFlags simple` () {
47+ val input = byteArrayOf(5 )
48+ val unpacked = PackedUtils .unpackFlags(input, 0 , 1 )
49+
50+ assertEquals(8 , unpacked.size, " Unpacking 1 byte should yield 8 booleans" )
51+ assertTrue(unpacked[0 ])
52+ assertFalse(unpacked[1 ])
53+ assertTrue(unpacked[2 ])
54+ assertFalse(unpacked[3 ])
55+ }
56+
57+ @Test
58+ fun `unpackFlags with offset` () {
59+ val input = byteArrayOf(0xFF .toByte(), 5 , 0xFF .toByte())
60+ val unpacked = PackedUtils .unpackFlags(input, 1 , 1 )
61+
62+ assertEquals(8 , unpacked.size)
63+ assertTrue(unpacked[0 ])
64+ assertFalse(unpacked[1 ])
65+ assertTrue(unpacked[2 ])
66+ assertFalse(unpacked[3 ])
67+ }
68+
69+ @Test
70+ fun `pack and unpack roundtrip exact boundary` () {
71+ val flags = BooleanArray (16 )
72+ flags[0 ] = true
73+ flags[7 ] = true
74+ flags[8 ] = true
75+ flags[15 ] = true
76+
77+ val packed = PackedUtils .packFlags(flags)
78+ assertEquals(2 , packed.size)
79+
80+ val unpacked = PackedUtils .unpackFlags(packed, 0 , packed.size)
81+ assertContentEquals(flags, unpacked)
82+ }
83+
84+ @Test
85+ fun `pack and unpack roundtrip padded boundary` () {
86+
87+ val flags = BooleanArray (10 )
88+ flags[0 ] = true
89+ flags[9 ] = true
90+
91+ val packed = PackedUtils .packFlags(flags)
92+ val unpacked = PackedUtils .unpackFlags(packed, 0 , packed.size)
93+
94+ assertEquals(16 , unpacked.size)
95+
96+ assertTrue(unpacked[0 ])
97+ assertTrue(unpacked[9 ])
98+ assertFalse(unpacked[1 ])
99+
100+ for (i in 10 until 16 ) {
101+ assertFalse(unpacked[i], " Padding bit $i should be false" )
102+ }
103+ }
104+
105+ @Test
106+ fun `unpackFlags throws on OOB` () {
107+ val input = byteArrayOf(1 , 2 )
108+ assertFailsWith<IllegalArgumentException > {
109+ PackedUtils .unpackFlags(input, 0 , 3 )
110+ }
111+ assertFailsWith<IllegalArgumentException > {
112+ PackedUtils .unpackFlags(input, 2 , 1 )
113+ }
114+ }
115+
7116 @Test
8117 fun `short roundtrip` () {
9118 val out = java.io.ByteArrayOutputStream ()
0 commit comments