package tokenize import ( "testing" ) func TestFork_CreatesForkOfInputAtSameCursorPosition(t *testing.T) { // Create input, accept the first rune. i := NewAPI("Testing") i.NextRune() i.Accept() // T AssertEqual(t, "T", i.String(), "accepted rune in input") // Fork child := i.Fork() AssertEqual(t, 1, i.stackFrame.offset, "parent offset") AssertEqual(t, 1, i.stackFrame.offset, "child offset") // Accept two runes via fork. i.NextRune() i.Accept() // e i.NextRune() i.Accept() // s AssertEqual(t, "es", i.String(), "result runes in fork") AssertEqual(t, 1, i.stackFrames[i.stackLevel-1].offset, "parent offset") AssertEqual(t, 3, i.stackFrame.offset, "child offset") // Merge fork back into parent i.Merge(child) i.Dispose(child) AssertEqual(t, "Tes", i.String(), "result runes in parent Input after Merge()") AssertEqual(t, 3, i.stackFrame.offset, "parent offset") } func TestGivenForkedChildWhichAcceptedRune_AfterMerging_RuneEndsUpInParentResult(t *testing.T) { i := NewAPI("Testing") i.NextRune() i.Accept() f1 := i.Fork() i.NextRune() i.Accept() f2 := i.Fork() i.NextRune() i.Accept() AssertEqual(t, "s", i.String(), "f2 String()") AssertEqual(t, 3, i.stackFrame.offset, "f2.offset A") i.Merge(f2) i.Dispose(f2) AssertEqual(t, "es", i.String(), "f1 String()") AssertEqual(t, 3, i.stackFrame.offset, "f1.offset A") i.Merge(f1) i.Dispose(f1) AssertEqual(t, "Tes", i.String(), "top-level API String()") AssertEqual(t, 3, i.stackFrame.offset, "f1.offset A") } func TestCallingAcceptAfterNextRune_AcceptsRuneAndMovesReadOffsetForward(t *testing.T) { i := NewAPI("Testing") r, _ := i.NextRune() AssertEqual(t, 'T', r, "result from 1st call to NextRune()") AssertTrue(t, i.lastRune == 'T', "API.lastRune after NextRune() is not 'T'") AssertTrue(t, i.runeRead, "API.runeRead after NextRune() is not true") i.Accept() AssertTrue(t, i.runeRead == false, "API.runeRead after Accept() is not false") AssertEqual(t, 1, i.stackFrame.offset, "API.stackFrame.offset") r, _ = i.NextRune() AssertEqual(t, 'e', r, "result from 2nd call to NextRune()") } func TestFlushInput(t *testing.T) { api := NewAPI("cool") // Flushing without any read data is okay. FlushInput() will return // false in this case, and nothing else happens. AssertTrue(t, api.FlushInput() == false, "flush input at start") api.NextRune() api.Accept() api.NextRune() api.Accept() AssertTrue(t, api.FlushInput() == true, "flush input after reading some data") AssertEqual(t, 0, api.stackFrame.offset, "offset after flush input") AssertTrue(t, api.FlushInput() == false, "flush input after flush input") // Read offset is now zero, but reading should continue after "co". api.NextRune() api.Accept() api.NextRune() api.Accept() AssertEqual(t, "cool", api.String(), "end result") } func TestInputFlusherWrapper(t *testing.T) { runeA := A.Rune('a') flushB := C.FlushInput(A.Rune('b')) api := NewAPI("abaab") runeA(api) AssertEqual(t, 1, api.stackFrame.offset, "offset after 1 read") AssertEqual(t, "a", api.String(), "runes after 1 read") flushB(api) AssertEqual(t, 0, api.stackFrame.offset, "offset after 2 reads + input flush") AssertEqual(t, "ab", api.String(), "runes after 2 reads") runeA(api) AssertEqual(t, 1, api.stackFrame.offset, "offset after 3 reads") AssertEqual(t, "aba", api.String(), "runes after 3 reads") runeA(api) AssertEqual(t, 2, api.stackFrame.offset, "offset after 4 reads") AssertEqual(t, "abaa", api.String(), "runes after 4 reads") flushB(api) AssertEqual(t, 0, api.stackFrame.offset, "offset after 5 reads + input flush") AssertEqual(t, "abaab", api.String(), "runes after 5 reads") } func AssertEqual(t *testing.T, expected interface{}, actual interface{}, forWhat string) { if expected != actual { t.Errorf( "Unexpected value for %s:\nexpected: %q\nactual: %q", forWhat, expected, actual) } } func AssertTrue(t *testing.T, b bool, assertion string) { if !b { t.Errorf("Assertion %s is false", assertion) } }