hexdump_test.gno
3.78 Kb · 126 lines
1package hexdump
2
3import (
4 "strings"
5 "testing"
6
7 "gno.land/p/nt/uassert/v0"
8)
9
10func TestOffset(t *testing.T) {
11 cases := []struct {
12 in int
13 want string
14 }{
15 {0, "00000000"},
16 {1, "00000001"},
17 {15, "0000000f"},
18 {16, "00000010"},
19 {255, "000000ff"},
20 {4096, "00001000"},
21 {-5, "00000000"}, // clamped
22 }
23 for _, c := range cases {
24 uassert.Equal(t, c.want, Offset(c.in))
25 }
26}
27
28func TestHex(t *testing.T) {
29 uassert.Equal(t, "00", Hex(0))
30 uassert.Equal(t, "0f", Hex(15))
31 uassert.Equal(t, "10", Hex(16))
32 uassert.Equal(t, "ff", Hex(255))
33 uassert.Equal(t, "41", Hex('A'))
34}
35
36func TestPrintable(t *testing.T) {
37 uassert.False(t, Printable(0x00), "NUL is not printable")
38 uassert.False(t, Printable(0x1f), "0x1f is below the printable range")
39 uassert.True(t, Printable(0x20), "space is printable")
40 uassert.True(t, Printable('A'))
41 uassert.True(t, Printable(0x7e), "~ is the last printable")
42 uassert.False(t, Printable(0x7f), "DEL is not printable")
43 uassert.False(t, Printable(0xff))
44}
45
46func TestASCII(t *testing.T) {
47 uassert.Equal(t, "ABC", ASCII([]byte("ABC")))
48 uassert.Equal(t, "...", ASCII([]byte{0x00, 0x01, 0x7f}))
49 uassert.Equal(t, "a.b", ASCII([]byte{'a', 0x00, 'b'}))
50 uassert.Equal(t, "", ASCII(nil))
51}
52
53// TestLineFullWidth pins the exact classic layout, including the extra space
54// between the two 8-byte groups.
55func TestLineFullWidth(t *testing.T) {
56 uassert.Equal(t,
57 "00000000 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 |0123456789abcdef|",
58 Line(0, []byte("0123456789abcdef")))
59}
60
61// TestLineShortChunkStaysAligned is the reason the padding exists: a partial
62// final line must not shift the ASCII gutter.
63func TestLineShortChunkStaysAligned(t *testing.T) {
64 full := Line(0, []byte("0123456789abcdef"))
65 short := Line(16, []byte("hi"))
66
67 uassert.Equal(t,
68 "00000010 68 69 |hi|",
69 short)
70 uassert.Equal(t, strings.Index(full, "|"), strings.Index(short, "|"),
71 "the ASCII gutter must start at the same column on a short line")
72}
73
74func TestLineEmptyChunk(t *testing.T) {
75 // All padding, empty gutter — still aligned.
76 l := Line(0, nil)
77 uassert.True(t, strings.HasSuffix(l, "||"), "empty chunk renders an empty gutter")
78 uassert.Equal(t, strings.Index(Line(0, []byte("x")), "|"), strings.Index(l, "|"))
79}
80
81func TestDumpMultiLine(t *testing.T) {
82 out, n := DumpString("0123456789abcdefhi")
83 uassert.Equal(t, 18, n)
84 uassert.Equal(t,
85 "00000000 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 |0123456789abcdef|\n"+
86 "00000010 68 69 |hi|\n",
87 out)
88}
89
90func TestDumpEmpty(t *testing.T) {
91 out, n := Dump(nil)
92 uassert.Equal(t, "", out)
93 uassert.Equal(t, 0, n)
94}
95
96func TestDumpNonPrintable(t *testing.T) {
97 out, n := Dump([]byte{0x00, 0x0a, 0x41})
98 uassert.Equal(t, 3, n)
99 uassert.Equal(t, "00000000 00 0a 41 |..A|\n", out)
100}
101
102// TestDumpTruncates pins the bound and the honest byte count.
103func TestDumpTruncates(t *testing.T) {
104 _, n := DumpString(strings.Repeat("x", MaxBytes+100))
105 uassert.Equal(t, MaxBytes, n, "input beyond MaxBytes is truncated")
106
107 _, n = DumpString(strings.Repeat("x", MaxBytes))
108 uassert.Equal(t, MaxBytes, n, "exactly MaxBytes is not truncated")
109}
110
111func TestDumpLineCount(t *testing.T) {
112 out, _ := DumpString(strings.Repeat("x", 33))
113 uassert.Equal(t, 3, strings.Count(out, "\n"), "33 bytes is 3 lines (16+16+1)")
114}
115
116// TestDumpRevealsInvisibleDifferences is the practical point of the package.
117func TestDumpRevealsInvisibleDifferences(t *testing.T) {
118 a, _ := DumpString("hi")
119 b, _ := DumpString("hi ")
120 uassert.False(t, a == b, "a trailing space is invisible rendered, obvious in a dump")
121
122 // "é" is two bytes, not one.
123 out, n := DumpString("é")
124 uassert.Equal(t, 2, n)
125 uassert.True(t, strings.Contains(out, "c3 a9"), "UTF-8 shows its real bytes")
126}