Commit 010ac23e authored by Matthew Holt's avatar Matthew Holt

More tests!

parent cdfc67db
...@@ -68,24 +68,22 @@ func (d *dispenser) NextLine() bool { ...@@ -68,24 +68,22 @@ func (d *dispenser) NextLine() bool {
return false return false
} }
// NextBlock advances the cursor to the next token only // NextBlock can be used as the condition of a for loop
// if the current token is an open curly brace on the // to load the next token as long as it opens a block or
// same line. If so, that token is consumed and this // is already in a block. It returns true if a token was
// function will return true until the closing curly // loaded, or false when the block's closing curly brace
// brace is consumed by this method. Usually, you would // was loaded and thus the block ended. Nested blocks are
// use this as the condition of a for loop to parse // not (currently) supported.
// tokens while being inside the block.
func (d *dispenser) NextBlock() bool { func (d *dispenser) NextBlock() bool {
if d.nesting > 0 { if d.nesting > 0 {
d.Next() d.Next()
if d.Val() == "}" { if d.Val() == "}" {
d.nesting-- d.nesting--
d.Next() // consume closing brace
return false return false
} }
return true return true
} }
if !d.NextArg() { if !d.NextArg() { // block must open on same line
return false return false
} }
if d.Val() != "{" { if d.Val() != "{" {
......
...@@ -5,12 +5,12 @@ import ( ...@@ -5,12 +5,12 @@ import (
"testing" "testing"
) )
func TestDispenser_cursor_Val_Next(t *testing.T) { func TestDispenser_Val_Next(t *testing.T) {
input := `host:port input := `host:port
dir1 arg1 dir1 arg1
dir2 arg2 arg3 dir2 arg2 arg3
dir3` dir3`
d := mockDispenser("test", input) d := makeTestDispenser("test", input)
if val := d.Val(); val != "" { if val := d.Val(); val != "" {
t.Fatalf("Val(): Should return empty string when no token loaded; got '%s'", val) t.Fatalf("Val(): Should return empty string when no token loaded; got '%s'", val)
...@@ -48,21 +48,27 @@ func TestDispenser_NextArg(t *testing.T) { ...@@ -48,21 +48,27 @@ func TestDispenser_NextArg(t *testing.T) {
input := `dir1 arg1 input := `dir1 arg1
dir2 arg2 arg3 dir2 arg2 arg3
dir3` dir3`
d := mockDispenser("test", input) d := makeTestDispenser("test", input)
assertNext := func(shouldLoad bool, expectedVal string) { assertNext := func(shouldLoad bool, expectedVal string, expectedCursor int) {
if d.Next() != shouldLoad { if d.Next() != shouldLoad {
t.Errorf("Next(): Should load token but got false instead (val: '%s')", d.Val()) t.Errorf("Next(): Should load token but got false instead (val: '%s')", d.Val())
} }
if d.cursor != expectedCursor {
t.Errorf("Next(): Expected cursor to be at %d, but it was %d", expectedCursor, d.cursor)
}
if val := d.Val(); val != expectedVal { if val := d.Val(); val != expectedVal {
t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val) t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val)
} }
} }
assertNextArg := func(expectedVal string, loadAnother bool) { assertNextArg := func(expectedVal string, loadAnother bool, expectedCursor int) {
if d.NextArg() != true { if d.NextArg() != true {
t.Error("NextArg(): Should load next argument but got false instead") t.Error("NextArg(): Should load next argument but got false instead")
} }
if d.cursor != expectedCursor {
t.Errorf("NextArg(): Expected cursor to be at %d, but it was %d", expectedCursor, d.cursor)
}
if val := d.Val(); val != expectedVal { if val := d.Val(); val != expectedVal {
t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val) t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val)
} }
...@@ -70,60 +76,84 @@ func TestDispenser_NextArg(t *testing.T) { ...@@ -70,60 +76,84 @@ func TestDispenser_NextArg(t *testing.T) {
if d.NextArg() != false { if d.NextArg() != false {
t.Fatalf("NextArg(): Should NOT load another argument, but got true instead (val: '%s')", d.Val()) t.Fatalf("NextArg(): Should NOT load another argument, but got true instead (val: '%s')", d.Val())
} }
if d.cursor != expectedCursor {
t.Errorf("NextArg(): Expected cursor to remain at %d, but it was %d", expectedCursor, d.cursor)
}
} }
} }
assertNext(true, "dir1") assertNext(true, "dir1", 0)
assertNextArg("arg1", false) assertNextArg("arg1", false, 1)
assertNext(true, "dir2") assertNext(true, "dir2", 2)
assertNextArg("arg2", true) assertNextArg("arg2", true, 3)
assertNextArg("arg3", false) assertNextArg("arg3", false, 4)
assertNext(true, "dir3") assertNext(true, "dir3", 5)
assertNext(false, "dir3") assertNext(false, "dir3", 5)
} }
func TestDispenser_NextLine(t *testing.T) { func TestDispenser_NextLine(t *testing.T) {
input := `host:port input := `host:port
dir1 arg1 dir1 arg1
dir2 arg2 arg3` dir2 arg2 arg3`
d := mockDispenser("test", input) d := makeTestDispenser("test", input)
assertNextLine := func(shouldLoad bool, expectedVal string) { assertNextLine := func(shouldLoad bool, expectedVal string, expectedCursor int) {
if d.NextLine() != shouldLoad { if d.NextLine() != shouldLoad {
t.Errorf("NextLine(): Should load token but got false instead (val: '%s')", d.Val()) t.Errorf("NextLine(): Should load token but got false instead (val: '%s')", d.Val())
} }
if d.cursor != expectedCursor {
t.Errorf("NextLine(): Expected cursor to be %d, instead was %d", expectedCursor, d.cursor)
}
if val := d.Val(); val != expectedVal { if val := d.Val(); val != expectedVal {
t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val) t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val)
} }
} }
assertNextLine(true, "host:port") assertNextLine(true, "host:port", 0)
assertNextLine(true, "dir1") assertNextLine(true, "dir1", 1)
assertNextLine(false, "dir1") assertNextLine(false, "dir1", 1)
d.Next() // arg1 d.Next() // arg1
assertNextLine(true, "dir2") assertNextLine(true, "dir2", 3)
assertNextLine(false, "dir2") assertNextLine(false, "dir2", 3)
d.Next() // arg2 d.Next() // arg2
assertNextLine(false, "arg2") assertNextLine(false, "arg2", 4)
d.Next() // arg3 d.Next() // arg3
assertNextLine(false, "arg3") assertNextLine(false, "arg3", 5)
} }
func TestDispenser_NextBlock_nesting(t *testing.T) { func TestDispenser_NextBlock(t *testing.T) {
/*input := `foobar1 { input := `foobar1 {
sub1 arg1 arg2 arg3 sub1 arg1
sub2 arg2 sub2
sub3
} }
foobar2 { foobar2 {
}`
d := makeTestDispenser("test", input)
assertNextBlock := func(shouldLoad bool, expectedCursor, expectedNesting int) {
if loaded := d.NextBlock(); loaded != shouldLoad {
t.Errorf("NextBlock(): Should return %v but got %v", shouldLoad, loaded)
}
if d.cursor != expectedCursor {
t.Errorf("NextBlock(): Expected cursor to be %d, was %d", expectedCursor, d.cursor)
} }
foobar3` if d.nesting != expectedNesting {
d := mockDispenser("test", input) t.Errorf("NextBlock(): Nesting should be %d, not %d", expectedNesting, d.nesting)
*/ }
// TODO }
assertNextBlock(false, -1, 0)
d.Next() // foobar1
assertNextBlock(true, 2, 1)
assertNextBlock(true, 3, 1)
assertNextBlock(true, 4, 1)
assertNextBlock(false, 5, 0)
d.Next() // foobar2
assertNextBlock(true, 8, 1)
assertNextBlock(false, 8, 0)
} }
func mockDispenser(filename, input string) dispenser { func makeTestDispenser(filename, input string) dispenser {
return dispenser{ return dispenser{
filename: filename, filename: filename,
cursor: -1, cursor: -1,
......
...@@ -34,13 +34,12 @@ type ( ...@@ -34,13 +34,12 @@ type (
// or it is on the same line. // or it is on the same line.
NextLine() bool NextLine() bool
// NextBlock advances the cursor to the next token only // NextBlock can be used as the condition of a for loop
// if the current token is an open curly brace on the // to load the next token as long as it opens a block or
// same line. If so, that token is consumed and this // is already in a block. It returns true if a token was
// function will return true until the closing curly // loaded, or false when the block's closing curly brace
// brace gets consumed by this method. Usually, you would // was loaded and thus the block ended. Nested blocks are
// use this as the condition of a for loop to parse // not (currently) supported.
// tokens while being inside a block.
NextBlock() bool NextBlock() bool
// Val gets the text of the current token. // Val gets the text of the current token.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment