Parse IPs and raw strings in arrays properly

This commit is contained in:
Derek Collison
2016-04-07 08:36:57 -07:00
parent 9bf172cf43
commit 433d62ec0a
24 changed files with 127 additions and 73 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2013-2015 Apcera Inc. All rights reserved.
// Copyright 2013-2016 Apcera Inc. All rights reserved.
// Customized heavily from
// https://github.com/BurntSushi/toml/blob/master/lex.go, which is based on
@@ -347,7 +347,7 @@ func lexValue(lx *lexer) stateFn {
return lexBlock
case isDigit(r):
lx.backup() // avoid an extra state and use the same as above
return lexNumberOrDateStart
return lexNumberOrDateOrIPStart
case r == '.': // special error case, be kind to users
return lx.errorf("Floats must start with a digit, not '.'.")
case isNL(r):
@@ -376,8 +376,7 @@ func lexArrayValue(lx *lexer) stateFn {
lx.backup()
fallthrough
case r == arrayValTerm:
return lx.errorf("Unexpected array value terminator '%v'.",
arrayValTerm)
return lx.errorf("Unexpected array value terminator '%v'.", arrayValTerm)
case r == arrayEnd:
return lexArrayEnd
}
@@ -603,15 +602,17 @@ func lexDubQuotedString(lx *lexer) stateFn {
return lexDubQuotedString
}
// lexString consumes the inner contents of a string. It assumes that the
// beginning '"' has already been consumed and ignored.
// lexString consumes the inner contents of a raw string.
func lexString(lx *lexer) stateFn {
r := lx.next()
switch {
case r == '\\':
return lexStringEscape
// Termination of non-quoted strings
case isNL(r) || r == eof || r == optValTerm || isWhitespace(r):
case isNL(r) || r == eof || r == optValTerm ||
r == arrayValTerm || r == arrayEnd ||
isWhitespace(r):
lx.backup()
if lx.isBool() {
lx.emit(itemBool)
@@ -702,9 +703,9 @@ func lexStringBinary(lx *lexer) stateFn {
return lexString
}
// lexNumberOrDateStart consumes either a (positive) integer, float or datetime.
// It assumes that NO negative sign has been consumed.
func lexNumberOrDateStart(lx *lexer) stateFn {
// lexNumberOrDateStart consumes either a (positive) integer, a float, a datetime, or IP.
// It assumes that NO negative sign has been consumed, that is triggered above.
func lexNumberOrDateOrIPStart(lx *lexer) stateFn {
r := lx.next()
if !isDigit(r) {
if r == '.' {
@@ -712,11 +713,11 @@ func lexNumberOrDateStart(lx *lexer) stateFn {
}
return lx.errorf("Expected a digit but got '%v'.", r)
}
return lexNumberOrDate
return lexNumberOrDateOrIP
}
// lexNumberOrDate consumes either a (positive) integer, float or datetime.
func lexNumberOrDate(lx *lexer) stateFn {
// lexNumberOrDateOrIP consumes either a (positive) integer, float, datetime or IP.
func lexNumberOrDateOrIP(lx *lexer) stateFn {
r := lx.next()
switch {
case r == '-':
@@ -725,7 +726,7 @@ func lexNumberOrDate(lx *lexer) stateFn {
}
return lexDateAfterYear
case isDigit(r):
return lexNumberOrDate
return lexNumberOrDateOrIP
case r == '.':
return lexFloatStart
}
@@ -786,7 +787,6 @@ func lexNumber(lx *lexer) stateFn {
case r == '.':
return lexFloatStart
}
lx.backup()
lx.emit(itemInteger)
return lx.pop()
@@ -811,11 +811,27 @@ func lexFloat(lx *lexer) stateFn {
return lexFloat
}
// Not a digit, if its another '.', need to see if we falsely assumed a float.
if r == '.' {
return lexIPAddr
}
lx.backup()
lx.emit(itemFloat)
return lx.pop()
}
// lexIPAddr consumes IP addrs, like 127.0.0.1:4222
func lexIPAddr(lx *lexer) stateFn {
r := lx.next()
if isDigit(r) || r == '.' || r == ':' {
return lexIPAddr
}
lx.backup()
lx.emit(itemString)
return lx.pop()
}
// lexCommentStart begins the lexing of a comment. It will emit
// itemCommentStart and consume no characters, passing control to lexComment.
func lexCommentStart(lx *lexer) stateFn {

View File

@@ -569,3 +569,48 @@ func TestBlockStringMultiLine(t *testing.T) {
lx := lex(mlblockexample)
expect(t, lx, expectedItems)
}
func TestUnquotedIPAddr(t *testing.T) {
expectedItems := []item{
{itemKey, "listen", 1},
{itemString, "127.0.0.1:4222", 1},
{itemEOF, "", 1},
}
lx := lex("listen: 127.0.0.1:4222")
expect(t, lx, expectedItems)
expectedItems = []item{
{itemKey, "listen", 1},
{itemString, "127.0.0.1", 1},
{itemEOF, "", 1},
}
lx = lex("listen: 127.0.0.1")
expect(t, lx, expectedItems)
expectedItems = []item{
{itemKey, "listen", 1},
{itemString, "apcera.me:80", 1},
{itemEOF, "", 1},
}
lx = lex("listen: apcera.me:80")
expect(t, lx, expectedItems)
expectedItems = []item{
{itemKey, "listen", 1},
{itemString, ":80", 1},
{itemEOF, "", 1},
}
lx = lex("listen = :80")
expect(t, lx, expectedItems)
expectedItems = []item{
{itemKey, "listen", 1},
{itemArrayStart, "", 1},
{itemString, "localhost:4222", 1},
{itemString, "localhost:4333", 1},
{itemArrayEnd, "", 1},
{itemEOF, "", 1},
}
lx = lex("listen = [localhost:4222, localhost:4333]")
expect(t, lx, expectedItems)
}

View File

@@ -2,7 +2,7 @@
# Cluster config file
port: 4242
net: apcera.me # net interface
net: localhost
authorization {
user: derek
@@ -14,7 +14,7 @@ pid_file: '/tmp/nats_cluster_test.pid'
log_file: '/tmp/nats_cluster_test.log'
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 4244
authorization {
@@ -28,9 +28,8 @@ cluster {
# in their routes definitions from above.
routes = [
nats-route://foo:bar@apcera.me:4245
nats-route://foo:bar@apcera.me:4246
nats-route://foo:bar@localhost:4245
nats-route://foo:bar@localhost:4246
]
}

View File

@@ -3,11 +3,11 @@
# Cluster Seed Node
port: 7222
net: '127.0.0.1'
net: 127.0.0.1
http_port: 9222
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 7248
}

View File

@@ -3,14 +3,14 @@
# Cluster Seed Node
port: 7222
net: '127.0.0.1'
net: 127.0.0.1
http_port: 9222
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 7248
tls {
# Route cert
cert_file: "../test/configs/certs/server-cert.pem"
@@ -22,5 +22,5 @@ cluster {
# Optional certificate authority verifying connected routes
# Required when we have self-signed CA, etc.
ca_file: "../test/configs/certs/ca.pem"
}
}
}

View File

@@ -1,12 +1,12 @@
# Copyright 2012-2015 Apcera Inc. All rights reserved.
# Copyright 2012-2016 Apcera Inc. All rights reserved.
# Cluster Server A
port: 7222
net: '127.0.0.1'
net: 127.0.0.1
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 7244
authorization {
@@ -23,4 +23,3 @@ cluster {
nats-route://ruser:top_secret@127.0.0.1:7246
]
}

View File

@@ -2,7 +2,7 @@
# Cluster Server A
host: '127.0.0.1'
host: 127.0.0.1
port: 7222
authorization {
@@ -12,7 +12,7 @@ authorization {
}
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 7244
authorization {

View File

@@ -1,12 +1,12 @@
# Copyright 2012-2015 Apcera Inc. All rights reserved.
# Copyright 2012-2016 Apcera Inc. All rights reserved.
# Cluster Server B
port: 7224
net: '127.0.0.1'
net: 127.0.0.1
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 7246
authorization {
@@ -23,4 +23,3 @@ cluster {
nats-route://ruser:top_secret@127.0.0.1:7244
]
}

View File

@@ -2,7 +2,7 @@
# Cluster Server B
host: '127.0.0.1'
host: 127.0.0.1
port: 7224
authorization {
@@ -12,7 +12,7 @@ authorization {
}
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 7246
authorization {

View File

@@ -2,7 +2,7 @@
# Simple config file
port: 4242
net: apcera.me # net interface
net: localhost
http_port: 8222

View File

@@ -2,7 +2,7 @@
# Simple TLS config file
port: 4443
net: apcera.me # net interface
net: localhost
tls {
cert_file: "./configs/certs/server.pem"

View File

@@ -2,7 +2,7 @@
# Simple TLS config file
port: 4443
net: apcera.me # net interface
net: localhost
tls {
cert_file: "./configs/certs/server.pem"
@@ -17,4 +17,3 @@ tls {
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
]
}

View File

@@ -2,7 +2,7 @@
# Simple TLS config file
port: 4443
net: apcera.me # net interface
net: localhost
tls {
cert_file: "./configs/certs/server.pem"

View File

@@ -2,7 +2,7 @@
# Simple TLS config file
port: 4443
net: apcera.me # net interface
net: localhost
tls {
cert_file: "./configs/certs/server.pem"
@@ -13,4 +13,3 @@ tls {
cipher_suites: [
]
}

View File

@@ -48,7 +48,7 @@ func TestOptions_RandomPort(t *testing.T) {
func TestConfigFile(t *testing.T) {
golden := &Options{
Host: "apcera.me",
Host: "localhost",
Port: 4242,
Username: "derek",
Password: "bella",
@@ -81,7 +81,7 @@ func TestConfigFile(t *testing.T) {
func TestTLSConfigFile(t *testing.T) {
golden := &Options{
Host: "apcera.me",
Host: "localhost",
Port: 4443,
Username: "derek",
Password: "buckley",
@@ -168,7 +168,7 @@ func TestTLSConfigFile(t *testing.T) {
func TestMergeOverrides(t *testing.T) {
golden := &Options{
Host: "apcera.me",
Host: "localhost",
Port: 2222,
Username: "derek",
Password: "spooky",

View File

@@ -19,7 +19,7 @@ func TestRouteConfig(t *testing.T) {
}
golden := &Options{
Host: "apcera.me",
Host: "localhost",
Port: 4242,
Username: "derek",
Password: "bella",
@@ -34,8 +34,8 @@ func TestRouteConfig(t *testing.T) {
}
// Setup URLs
r1, _ := url.Parse("nats-route://foo:bar@apcera.me:4245")
r2, _ := url.Parse("nats-route://foo:bar@apcera.me:4246")
r1, _ := url.Parse("nats-route://foo:bar@localhost:4245")
r2, _ := url.Parse("nats-route://foo:bar@localhost:4246")
golden.Routes = []*url.URL{r1, r2}

View File

@@ -1,9 +1,9 @@
# Copyright 2015 Apcera Inc. All rights reserved.
# Copyright 2015-2016 Apcera Inc. All rights reserved.
# Cluster Seed Node
port: 4222
net: '127.0.0.1'
net: 127.0.0.1
http_port: 8222

View File

@@ -1,8 +1,8 @@
# Copyright 2012-2015 Apcera Inc. All rights reserved.
# Copyright 2012-2016 Apcera Inc. All rights reserved.
# Cluster config file
host: "127.0.0.1"
host: 127.0.0.1
port: 4242
cluster {

View File

@@ -1,8 +1,8 @@
# Copyright 2015 Apcera Inc. All rights reserved.
# Copyright 2015-2016 Apcera Inc. All rights reserved.
# Config file to test overrides to client
host: "127.0.0.1"
host: 127.0.0.1
port: 4224
# maximum payload

View File

@@ -1,13 +1,13 @@
# Copyright 2015 Apcera Inc. All rights reserved.
# Copyright 2015-2016 Apcera Inc. All rights reserved.
# Cluster Seed Node
port: 4222
net: '127.0.0.1'
net: 127.0.0.1
http_port: 8222
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 4248
}

View File

@@ -1,9 +1,9 @@
# Copyright 2012-2013 Apcera Inc. All rights reserved.
# Copyright 2012-2016 Apcera Inc. All rights reserved.
# Cluster Server A
port: 4222
net: '127.0.0.1'
net: 127.0.0.1
cluster {
host: '127.0.0.1'
@@ -23,4 +23,3 @@ cluster {
nats-route://ruser:top_secret@127.0.0.1:4246
]
}

View File

@@ -1,12 +1,12 @@
# Copyright 2012-2015 Apcera Inc. All rights reserved.
# Copyright 2012-2016 Apcera Inc. All rights reserved.
# Cluster Server A
host: '127.0.0.1'
host: 127.0.0.1
port: 4222
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 4244
tls {

View File

@@ -1,12 +1,12 @@
# Copyright 2012-2013 Apcera Inc. All rights reserved.
# Copyright 2012-2016 Apcera Inc. All rights reserved.
# Cluster Server B
port: 4224
net: '127.0.0.1'
net: 127.0.0.1
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 4246
authorization {
@@ -23,4 +23,3 @@ cluster {
nats-route://ruser:top_secret@127.0.0.1:4244
]
}

View File

@@ -1,12 +1,12 @@
# Copyright 2012-2015 Apcera Inc. All rights reserved.
# Copyright 2012-2016 Apcera Inc. All rights reserved.
# Cluster Server B
host: '127.0.0.1'
host: 127.0.0.1
port: 4224
cluster {
host: '127.0.0.1'
host: 127.0.0.1
port: 4246
tls {