diff --git a/conf/lex.go b/conf/lex.go index 27a427fa..77199f70 100644 --- a/conf/lex.go +++ b/conf/lex.go @@ -246,7 +246,7 @@ func lexKeyStart(lx *lexer) stateFn { r := lx.peek() switch { case isKeySeparator(r): - return lx.errorf("Unexpected key separator '%v'.", r) + return lx.errorf("Unexpected key separator '%v'", r) case isWhitespace(r) || isNL(r): lx.next() return lexSkip(lx, lexKeyStart) @@ -349,7 +349,7 @@ func lexValue(lx *lexer) stateFn { lx.backup() // avoid an extra state and use the same as above return lexNumberOrDateOrIPStart case r == '.': // special error case, be kind to users - return lx.errorf("Floats must start with a digit, not '.'.") + return lx.errorf("Floats must start with a digit") case isNL(r): return lx.errorf("Expected value but found new line") } diff --git a/conf/lex_test.go b/conf/lex_test.go index 9e6ea55e..521af4b2 100644 --- a/conf/lex_test.go +++ b/conf/lex_test.go @@ -1,22 +1,22 @@ package conf -import ( - "testing" -) +import "testing" // Test to make sure we get what we expect. func expect(t *testing.T, lx *lexer, items []item) { for i := 0; i < len(items); i++ { item := lx.nextItem() + _ = item.String() if item.typ == itemEOF { break - } else if item.typ == itemError { - t.Fatal(item.val) } if item != items[i] { t.Fatalf("Testing: '%s'\nExpected %q, received %q\n", lx.input, items[i], item) } + if item.typ == itemError { + break + } } } @@ -77,6 +77,20 @@ func TestSimpleKeyIntegerValues(t *testing.T) { expect(t, lx, expectedItems) } +func TestSimpleKeyNegativeIntegerValues(t *testing.T) { + expectedItems := []item{ + {itemKey, "foo", 1}, + {itemInteger, "-123", 1}, + {itemEOF, "", 1}, + } + lx := lex("foo = -123") + expect(t, lx, expectedItems) + lx = lex("foo=-123") + expect(t, lx, expectedItems) + lx = lex("foo=-123\r\n") + expect(t, lx, expectedItems) +} + func TestSimpleKeyFloatValues(t *testing.T) { expectedItems := []item{ {itemKey, "foo", 1}, @@ -91,6 +105,25 @@ func TestSimpleKeyFloatValues(t *testing.T) { expect(t, lx, expectedItems) } +func TestBadFloatValues(t *testing.T) { + expectedItems := []item{ + {itemKey, "foo", 1}, + {itemError, "Floats must start with a digit", 1}, + {itemEOF, "", 1}, + } + lx := lex("foo = .2") + expect(t, lx, expectedItems) +} + +func TestBadKey(t *testing.T) { + expectedItems := []item{ + {itemError, "Unexpected key separator ':'", 1}, + {itemEOF, "", 1}, + } + lx := lex(" :foo = 22") + expect(t, lx, expectedItems) +} + func TestSimpleKeyBoolValues(t *testing.T) { expectedItems := []item{ {itemKey, "foo", 1}, @@ -134,6 +167,31 @@ func TestTopValuesWithComments(t *testing.T) { expect(t, lx, expectedItems) } +func TestRawString(t *testing.T) { + expectedItems := []item{ + {itemKey, "foo", 1}, + {itemString, "bar", 1}, + {itemEOF, "", 1}, + } + + lx := lex("foo = bar") + expect(t, lx, expectedItems) + + lx = lex(`foo = bar' `) + expect(t, lx, expectedItems) +} + +func TestDateValues(t *testing.T) { + expectedItems := []item{ + {itemKey, "foo", 1}, + {itemDatetime, "2016-05-04T18:53:41Z", 1}, + {itemEOF, "", 1}, + } + + lx := lex("foo = 2016-05-04T18:53:41Z") + expect(t, lx, expectedItems) +} + func TestArrays(t *testing.T) { expectedItems := []item{ {itemKey, "foo", 1}, @@ -158,7 +216,7 @@ var mlArray = ` foo = [ 1, # One 2, // Two - 3 , // Three + 3 # Three 'bar' , "bar" ] @@ -348,6 +406,32 @@ func TestWhitespaceKeySep(t *testing.T) { expect(t, lx, expectedItems) } +var escString = ` +foo = \t +bar = \r +baz = \n +q = \" +bs = \\ +` + +func TestEscapedString(t *testing.T) { + expectedItems := []item{ + {itemKey, "foo", 2}, + {itemString, `\t`, 2}, + {itemKey, "bar", 3}, + {itemString, `\r`, 3}, + {itemKey, "baz", 4}, + {itemString, `\n`, 4}, + {itemKey, "q", 5}, + {itemString, `\"`, 5}, + {itemKey, "bs", 6}, + {itemString, `\\`, 6}, + {itemEOF, "", 6}, + } + lx := lex(escString) + expect(t, lx, expectedItems) +} + var nestedWhitespaceMap = ` foo { host { diff --git a/conf/parse_test.go b/conf/parse_test.go index fda9b6e4..db8b0210 100644 --- a/conf/parse_test.go +++ b/conf/parse_test.go @@ -3,6 +3,7 @@ package conf import ( "reflect" "testing" + "time" ) // Test to make sure we get what we expect. @@ -130,3 +131,18 @@ func TestSample4(t *testing.T) { } test(t, sample4, ex) } + +var sample5 = ` + now = 2016-05-04T18:53:41Z + gmt = false + +` + +func TestSample5(t *testing.T) { + dt, _ := time.Parse("2006-01-02T15:04:05Z", "2016-05-04T18:53:41Z") + ex := map[string]interface{}{ + "now": dt, + "gmt": false, + } + test(t, sample5, ex) +}