From 010ac23e8a51a56b9c88597a24e50d397a445eff Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Sat, 21 Mar 2015 11:18:37 -0600 Subject: [PATCH] More tests! --- config/dispenser.go | 16 +++---- config/dispenser_test.go | 94 ++++++++++++++++++++++++++-------------- middleware/middleware.go | 13 +++--- 3 files changed, 75 insertions(+), 48 deletions(-) diff --git a/config/dispenser.go b/config/dispenser.go index 597c14234..f2c9a121a 100644 --- a/config/dispenser.go +++ b/config/dispenser.go @@ -68,24 +68,22 @@ func (d *dispenser) NextLine() bool { return false } -// NextBlock advances the cursor to the next token only -// if the current token is an open curly brace on the -// same line. If so, that token is consumed and this -// function will return true until the closing curly -// brace is consumed by this method. Usually, you would -// use this as the condition of a for loop to parse -// tokens while being inside the block. +// NextBlock can be used as the condition of a for loop +// to load the next token as long as it opens a block or +// is already in a block. It returns true if a token was +// loaded, or false when the block's closing curly brace +// was loaded and thus the block ended. Nested blocks are +// not (currently) supported. func (d *dispenser) NextBlock() bool { if d.nesting > 0 { d.Next() if d.Val() == "}" { d.nesting-- - d.Next() // consume closing brace return false } return true } - if !d.NextArg() { + if !d.NextArg() { // block must open on same line return false } if d.Val() != "{" { diff --git a/config/dispenser_test.go b/config/dispenser_test.go index e0fcd4514..352ca2829 100644 --- a/config/dispenser_test.go +++ b/config/dispenser_test.go @@ -5,12 +5,12 @@ import ( "testing" ) -func TestDispenser_cursor_Val_Next(t *testing.T) { +func TestDispenser_Val_Next(t *testing.T) { input := `host:port dir1 arg1 dir2 arg2 arg3 dir3` - d := mockDispenser("test", input) + d := makeTestDispenser("test", input) if val := d.Val(); 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) { input := `dir1 arg1 dir2 arg2 arg3 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 { 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 { 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 { 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 { t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val) } @@ -70,60 +76,84 @@ func TestDispenser_NextArg(t *testing.T) { if d.NextArg() != false { 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") - assertNextArg("arg1", false) - assertNext(true, "dir2") - assertNextArg("arg2", true) - assertNextArg("arg3", false) - assertNext(true, "dir3") - assertNext(false, "dir3") + assertNext(true, "dir1", 0) + assertNextArg("arg1", false, 1) + assertNext(true, "dir2", 2) + assertNextArg("arg2", true, 3) + assertNextArg("arg3", false, 4) + assertNext(true, "dir3", 5) + assertNext(false, "dir3", 5) } func TestDispenser_NextLine(t *testing.T) { input := `host:port dir1 arg1 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 { 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 { t.Errorf("Val(): Expected '%s' but got '%s'", expectedVal, val) } } - assertNextLine(true, "host:port") - assertNextLine(true, "dir1") - assertNextLine(false, "dir1") + assertNextLine(true, "host:port", 0) + assertNextLine(true, "dir1", 1) + assertNextLine(false, "dir1", 1) d.Next() // arg1 - assertNextLine(true, "dir2") - assertNextLine(false, "dir2") + assertNextLine(true, "dir2", 3) + assertNextLine(false, "dir2", 3) d.Next() // arg2 - assertNextLine(false, "arg2") + assertNextLine(false, "arg2", 4) d.Next() // arg3 - assertNextLine(false, "arg3") + assertNextLine(false, "arg3", 5) } -func TestDispenser_NextBlock_nesting(t *testing.T) { - /*input := `foobar1 { - sub1 arg1 arg2 arg3 - sub2 arg2 - sub3 +func TestDispenser_NextBlock(t *testing.T) { + input := `foobar1 { + sub1 arg1 + sub2 } foobar2 { - } - foobar3` - d := mockDispenser("test", input) - */ - // TODO + }` + 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) + } + if d.nesting != expectedNesting { + t.Errorf("NextBlock(): Nesting should be %d, not %d", expectedNesting, d.nesting) + } + } + + 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{ filename: filename, cursor: -1, diff --git a/middleware/middleware.go b/middleware/middleware.go index 3ae3256bf..57f129cf3 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -34,13 +34,12 @@ type ( // or it is on the same line. NextLine() bool - // NextBlock advances the cursor to the next token only - // if the current token is an open curly brace on the - // same line. If so, that token is consumed and this - // function will return true until the closing curly - // brace gets consumed by this method. Usually, you would - // use this as the condition of a for loop to parse - // tokens while being inside a block. + // NextBlock can be used as the condition of a for loop + // to load the next token as long as it opens a block or + // is already in a block. It returns true if a token was + // loaded, or false when the block's closing curly brace + // was loaded and thus the block ended. Nested blocks are + // not (currently) supported. NextBlock() bool // Val gets the text of the current token.