1package buffruneio
2
3import (
4	"strings"
5	"testing"
6)
7
8func assumeRunesArray(t *testing.T, expected []rune, got []rune) {
9	if len(expected) != len(got) {
10		t.Fatal("expected", len(expected), "runes, but got", len(got))
11	}
12	for i := 0; i < len(got); i++ {
13		if expected[i] != got[i] {
14			t.Fatal("expected rune", expected[i], "at index", i, "but got", got[i])
15		}
16	}
17}
18
19func assumeRune(t *testing.T, rd *Reader, r rune) {
20	gotRune, err := rd.ReadRune()
21	if err != nil {
22		t.Fatal("unexpected error", err)
23	}
24	if gotRune != r {
25		t.Fatal("got", string(gotRune),
26			"(", []byte(string(gotRune)), ")",
27			"expected", string(r),
28			"(", []byte(string(r)), ")")
29	}
30}
31
32func TestReadString(t *testing.T) {
33	s := "hello"
34	rd := NewReader(strings.NewReader(s))
35
36	assumeRune(t, rd, 'h')
37	assumeRune(t, rd, 'e')
38	assumeRune(t, rd, 'l')
39	assumeRune(t, rd, 'l')
40	assumeRune(t, rd, 'o')
41	assumeRune(t, rd, EOF)
42}
43
44func TestMultipleEOF(t *testing.T) {
45	s := ""
46	rd := NewReader(strings.NewReader(s))
47
48	assumeRune(t, rd, EOF)
49	assumeRune(t, rd, EOF)
50}
51
52func TestUnread(t *testing.T) {
53	s := "ab"
54	rd := NewReader(strings.NewReader(s))
55
56	assumeRune(t, rd, 'a')
57	assumeRune(t, rd, 'b')
58	rd.UnreadRune()
59	assumeRune(t, rd, 'b')
60	assumeRune(t, rd, EOF)
61}
62
63func TestUnreadEOF(t *testing.T) {
64	s := ""
65	rd := NewReader(strings.NewReader(s))
66
67	rd.UnreadRune()
68	assumeRune(t, rd, EOF)
69	assumeRune(t, rd, EOF)
70	rd.UnreadRune()
71	assumeRune(t, rd, EOF)
72}
73
74func TestForget(t *testing.T) {
75	s := "hello"
76	rd := NewReader(strings.NewReader(s))
77
78	assumeRune(t, rd, 'h')
79	assumeRune(t, rd, 'e')
80	assumeRune(t, rd, 'l')
81	assumeRune(t, rd, 'l')
82	rd.Forget()
83	if rd.UnreadRune() != ErrNoRuneToUnread {
84		t.Fatal("no rune should be available")
85	}
86}
87
88func TestForgetEmpty(t *testing.T) {
89	s := ""
90	rd := NewReader(strings.NewReader(s))
91
92	rd.Forget()
93	assumeRune(t, rd, EOF)
94	rd.Forget()
95}
96
97func TestPeekEmpty(t *testing.T) {
98	s := ""
99	rd := NewReader(strings.NewReader(s))
100
101	runes := rd.Peek(1)
102	if len(runes) != 1 {
103		t.Fatal("incorrect number of runes", len(runes))
104	}
105	if runes[0] != EOF {
106		t.Fatal("incorrect rune", runes[0])
107	}
108}
109
110func TestPeek(t *testing.T) {
111	s := "a"
112	rd := NewReader(strings.NewReader(s))
113
114	runes := rd.Peek(1)
115	assumeRunesArray(t, []rune{'a'}, runes)
116
117	runes = rd.Peek(1)
118	assumeRunesArray(t, []rune{'a'}, runes)
119
120	assumeRune(t, rd, 'a')
121	runes = rd.Peek(1)
122	assumeRunesArray(t, []rune{EOF}, runes)
123
124	assumeRune(t, rd, EOF)
125}
126
127func TestPeekLarge(t *testing.T) {
128	s := "abcdefg"
129	rd := NewReader(strings.NewReader(s))
130
131	runes := rd.Peek(100)
132	if len(runes) != len(s)+1 {
133		t.Fatal("incorrect number of runes", len(runes))
134	}
135	assumeRunesArray(t, []rune{'a', 'b', 'c', 'd', 'e', 'f', 'g', EOF}, runes)
136}
137