aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parser/reader_test.go178
1 files changed, 178 insertions, 0 deletions
diff --git a/parser/reader_test.go b/parser/reader_test.go
new file mode 100644
index 0000000..f80f52c
--- /dev/null
+++ b/parser/reader_test.go
@@ -0,0 +1,178 @@
+package parser
+
+import (
+ "bufio"
+ "io"
+ "strings"
+ "testing"
+)
+
+func TestPeekRune(t *testing.T) {
+ s := "Ta’ Ħaġrat"
+ reader := reader{r: bufio.NewReader(strings.NewReader(s))}
+
+ for _, r := range s {
+ r1, err := reader.peekRune()
+ if err != nil && !(err == io.EOF && r == 't') {
+ t.Fatalf("reader.peekRune() failed with ‘%T’ at rune ‘%c’", err, r)
+ }
+
+ r2, _ := reader.readRune()
+ if r1 != r2 {
+ t.Fatalf("reader.peekRune() peaked ‘%c’ but the next read rune was ‘%c’", r1, r2)
+ }
+ }
+}
+
+func TestUnreadRune(t *testing.T) {
+ s := "Ta’ Ħaġrat"
+ reader := reader{r: bufio.NewReader(strings.NewReader(s))}
+
+ for range s {
+ r1, _ := reader.readRune()
+ if err := reader.unreadRune(); err != nil {
+ t.Fatalf("reader.unreadRune() failed with ‘%T’ when unreading rune ‘%c’", err, r1)
+ }
+ r2, _ := reader.readRune()
+ if r1 != r2 {
+ t.Fatalf("reader.readRune() returned ‘%c’ after unreading ‘%c’", r2, r1)
+ }
+ }
+}
+
+func TestUnreadRunePosTracking(t *testing.T) {
+ s := "Ta’ Ħaġrat\nIJsselmeer"
+ reader := reader{r: bufio.NewReader(strings.NewReader(s))}
+
+ for i := range []rune(s) {
+ r, _ := reader.readRune()
+
+ if err := reader.unreadRune(); err != nil {
+ t.Fatalf("reader.unreadRune() failed with ‘%T’ when unreading rune ‘%c’", err, r)
+ }
+
+ // Ensure we tracked the row correctly
+ switch {
+ case i < 11 && reader.pos.row != 0:
+ t.Fatalf("Expected reader to be on row 0 after unreading rune ‘%c’ but got row %d", r, reader.pos.row)
+ case i >= 11 && reader.pos.row != 1:
+ t.Fatalf("Expected reader to be on row 1 after unreading rune ‘%c’ but got row %d", r, reader.pos.row)
+ }
+
+ // Ensure we tracked the column correctly
+ switch {
+ case i < 11 && reader.pos.col != uint(i):
+ t.Fatalf("Expected reader to be on col %d after unreading rune ‘%c’ but got col %d", i, r, reader.pos.col)
+ case i == 11 && reader.pos.col != 0:
+ t.Fatalf("Expected reader to be on col 0 after unreading rune ‘\\n’ but got col %d", reader.pos.col)
+ case i > 11 && reader.pos.col != uint(i)-11:
+ t.Fatalf("Expected reader to be on col %d after unreading rune ‘%c’ but got col %d", i-10, r, reader.pos.col)
+ }
+
+ reader.readRune()
+ }
+}
+
+func TestReadRune(t *testing.T) {
+ s := "Ta’ Ħaġrat"
+ reader := reader{r: bufio.NewReader(strings.NewReader(s))}
+
+ for _, r1 := range s {
+ r2, err := reader.readRune()
+ if err != nil {
+ t.Fatalf("reader.readRune() failed with ‘%T’", err)
+ }
+ if r1 != r2 {
+ t.Fatalf("reader.readRune() read ‘%c’ but ‘%c’ was expected", r1, r2)
+ }
+ }
+
+ _, err := reader.readRune()
+ switch {
+ case err == nil:
+ t.Fatal("reader.readRune() expected to fail but didn’t")
+ case err != io.EOF:
+ t.Fatalf("reader.readRune() expected to fail with io.EOF but got ‘%T’", err)
+ }
+}
+
+func TestReadRunePosTracking(t *testing.T) {
+ s := "Ta’ Ħaġrat\nIJsselmeer"
+ line1 := true
+ reader := reader{r: bufio.NewReader(strings.NewReader(s))}
+
+ for i := range []rune(s) {
+ // Track the line we’re on
+ r, _ := reader.readRune()
+ if r == '\n' {
+ line1 = false
+ }
+
+ // Ensure we tracked the row correctly
+ switch {
+ case line1 && reader.pos.row != 0:
+ t.Fatalf("Expected reader to be on row 0 when reading rune ‘%c’ but got row %d", r, reader.pos.row)
+ case !line1 && reader.pos.row != 1:
+ t.Fatalf("Expected reader to be on row 1 when reading rune ‘%c’ but got row %d", r, reader.pos.row)
+ }
+
+ // Ensure we tracked the column correctly
+ switch {
+ case i < 10 && reader.pos.col != uint(i)+1:
+ t.Fatalf("Expected reader to be on col %d when reading rune ‘%c’ but got col %d", i, r, reader.pos.col)
+ case i == 10 && reader.pos.col != 0:
+ t.Fatalf("Expected reader to be on col 0 when reading rune ‘\\n’ but got col %d", reader.pos.col)
+ case i > 10 && reader.pos.col != uint(i)-10:
+ t.Fatalf("Expected reader to be on col %d when reading rune ‘%c’ but got col %d", i-10, r, reader.pos.col)
+ }
+ }
+}
+
+func TestReadNonSpaceRune(t *testing.T) {
+ s := "Ta’ Ħaġrat \t\n IJsselmeer"
+ reader := reader{r: bufio.NewReader(strings.NewReader(s))}
+ readUntil := func(target rune) {
+ for {
+ if r, _ := reader.readRune(); r == target {
+ break
+ }
+ }
+ }
+ assertNext := func(target rune) {
+ if r, err := reader.readNonSpaceRune(); err != nil {
+ t.Fatalf("reader.readNonSpaceRune() failed with ‘%T’", err)
+ } else if r != target {
+ t.Fatalf("reader.readNonSpaceRune() expected to return ‘%c’ but returned ‘%c’", target, r)
+ }
+ }
+
+ readUntil('’')
+ assertNext('Ħ')
+ readUntil('t')
+ assertNext('IJ')
+}
+
+func TestSkipSpaces(t *testing.T) {
+ s := "Ta’ Ħaġrat \t\n IJsselmeer"
+ reader := reader{r: bufio.NewReader(strings.NewReader(s))}
+ readUntil := func(target rune) {
+ for {
+ if r, _ := reader.readRune(); r == target {
+ break
+ }
+ }
+ }
+ assertNext := func(target rune) {
+ if err := reader.skipSpaces(); err != nil {
+ t.Fatalf("reader.skipSpaces() failed with ‘%T’", err)
+ }
+ if r, _ := reader.readRune(); r != target {
+ t.Fatalf("reader.readRune() expected to return ‘%c’ but returned ‘%c’", target, r)
+ }
+ }
+
+ readUntil('’')
+ assertNext('Ħ')
+ readUntil('t')
+ assertNext('IJ')
+}