mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
386 lines
8.0 KiB
Go
386 lines
8.0 KiB
Go
package conf
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// Test to make sure we get what we expect.
|
|
|
|
func test(t *testing.T, data string, ex map[string]interface{}) {
|
|
t.Helper()
|
|
m, err := Parse(data)
|
|
if err != nil {
|
|
t.Fatalf("Received err: %v\n", err)
|
|
}
|
|
if m == nil {
|
|
t.Fatal("Received nil map")
|
|
}
|
|
|
|
if !reflect.DeepEqual(m, ex) {
|
|
t.Fatalf("Not Equal:\nReceived: '%+v'\nExpected: '%+v'\n", m, ex)
|
|
}
|
|
}
|
|
|
|
func TestSimpleTopLevel(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"foo": "1",
|
|
"bar": float64(2.2),
|
|
"baz": true,
|
|
"boo": int64(22),
|
|
}
|
|
test(t, "foo='1'; bar=2.2; baz=true; boo=22", ex)
|
|
}
|
|
|
|
func TestBools(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"foo": true,
|
|
}
|
|
test(t, "foo=true", ex)
|
|
test(t, "foo=TRUE", ex)
|
|
test(t, "foo=true", ex)
|
|
test(t, "foo=yes", ex)
|
|
test(t, "foo=on", ex)
|
|
}
|
|
|
|
var varSample = `
|
|
index = 22
|
|
foo = $index
|
|
`
|
|
|
|
func TestSimpleVariable(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"index": int64(22),
|
|
"foo": int64(22),
|
|
}
|
|
test(t, varSample, ex)
|
|
}
|
|
|
|
var varNestedSample = `
|
|
index = 22
|
|
nest {
|
|
index = 11
|
|
foo = $index
|
|
}
|
|
bar = $index
|
|
`
|
|
|
|
func TestNestedVariable(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"index": int64(22),
|
|
"nest": map[string]interface{}{
|
|
"index": int64(11),
|
|
"foo": int64(11),
|
|
},
|
|
"bar": int64(22),
|
|
}
|
|
test(t, varNestedSample, ex)
|
|
}
|
|
|
|
func TestMissingVariable(t *testing.T) {
|
|
_, err := Parse("foo=$index")
|
|
if err == nil {
|
|
t.Fatalf("Expected an error for a missing variable, got none")
|
|
}
|
|
if !strings.HasPrefix(err.Error(), "variable reference") {
|
|
t.Fatalf("Wanted a variable reference err, got %q\n", err)
|
|
}
|
|
}
|
|
|
|
func TestEnvVariable(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"foo": int64(22),
|
|
}
|
|
evar := "__UNIQ22__"
|
|
os.Setenv(evar, "22")
|
|
defer os.Unsetenv(evar)
|
|
test(t, fmt.Sprintf("foo = $%s", evar), ex)
|
|
}
|
|
|
|
func TestEnvVariableString(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"foo": "xyz",
|
|
}
|
|
evar := "__UNIQ22__"
|
|
os.Setenv(evar, "xyz")
|
|
defer os.Unsetenv(evar)
|
|
test(t, fmt.Sprintf("foo = $%s", evar), ex)
|
|
}
|
|
|
|
func TestEnvVariableStringStartingWithNumber(t *testing.T) {
|
|
evar := "__UNIQ22__"
|
|
os.Setenv(evar, "3xyz")
|
|
defer os.Unsetenv(evar)
|
|
|
|
_, err := Parse("foo = $%s")
|
|
if err == nil {
|
|
t.Fatalf("Expected err not being able to process string: %v\n", err)
|
|
}
|
|
}
|
|
|
|
func TestEnvVariableStringStartingWithNumberUsingQuotes(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"foo": "3xyz",
|
|
}
|
|
evar := "__UNIQ22__"
|
|
os.Setenv(evar, "'3xyz'")
|
|
defer os.Unsetenv(evar)
|
|
test(t, fmt.Sprintf("foo = $%s", evar), ex)
|
|
}
|
|
|
|
func TestBcryptVariable(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"password": "$2a$11$ooo",
|
|
}
|
|
test(t, "password: $2a$11$ooo", ex)
|
|
}
|
|
|
|
var easynum = `
|
|
k = 8k
|
|
kb = 4kb
|
|
ki = 3ki
|
|
kib = 4ki
|
|
m = 1m
|
|
mb = 2MB
|
|
mi = 2Mi
|
|
mib = 64MiB
|
|
g = 2g
|
|
gb = 22GB
|
|
gi = 22Gi
|
|
gib = 22GiB
|
|
tb = 22TB
|
|
ti = 22Ti
|
|
tib = 22TiB
|
|
pb = 22PB
|
|
pi = 22Pi
|
|
pib = 22PiB
|
|
`
|
|
|
|
func TestConvenientNumbers(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"k": int64(8 * 1000),
|
|
"kb": int64(4 * 1024),
|
|
"ki": int64(3 * 1024),
|
|
"kib": int64(4 * 1024),
|
|
"m": int64(1000 * 1000),
|
|
"mb": int64(2 * 1024 * 1024),
|
|
"mi": int64(2 * 1024 * 1024),
|
|
"mib": int64(64 * 1024 * 1024),
|
|
"g": int64(2 * 1000 * 1000 * 1000),
|
|
"gb": int64(22 * 1024 * 1024 * 1024),
|
|
"gi": int64(22 * 1024 * 1024 * 1024),
|
|
"gib": int64(22 * 1024 * 1024 * 1024),
|
|
"tb": int64(22 * 1024 * 1024 * 1024 * 1024),
|
|
"ti": int64(22 * 1024 * 1024 * 1024 * 1024),
|
|
"tib": int64(22 * 1024 * 1024 * 1024 * 1024),
|
|
"pb": int64(22 * 1024 * 1024 * 1024 * 1024 * 1024),
|
|
"pi": int64(22 * 1024 * 1024 * 1024 * 1024 * 1024),
|
|
"pib": int64(22 * 1024 * 1024 * 1024 * 1024 * 1024),
|
|
}
|
|
test(t, easynum, ex)
|
|
}
|
|
|
|
var sample1 = `
|
|
foo {
|
|
host {
|
|
ip = '127.0.0.1'
|
|
port = 4242
|
|
}
|
|
servers = [ "a.com", "b.com", "c.com"]
|
|
}
|
|
`
|
|
|
|
func TestSample1(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"foo": map[string]interface{}{
|
|
"host": map[string]interface{}{
|
|
"ip": "127.0.0.1",
|
|
"port": int64(4242),
|
|
},
|
|
"servers": []interface{}{"a.com", "b.com", "c.com"},
|
|
},
|
|
}
|
|
test(t, sample1, ex)
|
|
}
|
|
|
|
var cluster = `
|
|
cluster {
|
|
port: 4244
|
|
|
|
authorization {
|
|
user: route_user
|
|
password: top_secret
|
|
timeout: 1
|
|
}
|
|
|
|
# Routes are actively solicited and connected to from this server.
|
|
# Other servers can connect to us if they supply the correct credentials
|
|
# in their routes definitions from above.
|
|
|
|
// Test both styles of comments
|
|
|
|
routes = [
|
|
nats-route://foo:bar@apcera.me:4245
|
|
nats-route://foo:bar@apcera.me:4246
|
|
]
|
|
}
|
|
`
|
|
|
|
func TestSample2(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"cluster": map[string]interface{}{
|
|
"port": int64(4244),
|
|
"authorization": map[string]interface{}{
|
|
"user": "route_user",
|
|
"password": "top_secret",
|
|
"timeout": int64(1),
|
|
},
|
|
"routes": []interface{}{
|
|
"nats-route://foo:bar@apcera.me:4245",
|
|
"nats-route://foo:bar@apcera.me:4246",
|
|
},
|
|
},
|
|
}
|
|
|
|
test(t, cluster, ex)
|
|
}
|
|
|
|
var sample3 = `
|
|
foo {
|
|
expr = '(true == "false")'
|
|
text = 'This is a multi-line
|
|
text block.'
|
|
}
|
|
`
|
|
|
|
func TestSample3(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"foo": map[string]interface{}{
|
|
"expr": "(true == \"false\")",
|
|
"text": "This is a multi-line\ntext block.",
|
|
},
|
|
}
|
|
test(t, sample3, ex)
|
|
}
|
|
|
|
var sample4 = `
|
|
array [
|
|
{ abc: 123 }
|
|
{ xyz: "word" }
|
|
]
|
|
`
|
|
|
|
func TestSample4(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"array": []interface{}{
|
|
map[string]interface{}{"abc": int64(123)},
|
|
map[string]interface{}{"xyz": "word"},
|
|
},
|
|
}
|
|
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)
|
|
}
|
|
|
|
func TestIncludes(t *testing.T) {
|
|
ex := map[string]interface{}{
|
|
"listen": "127.0.0.1:4222",
|
|
"authorization": map[string]interface{}{
|
|
"ALICE_PASS": "$2a$10$UHR6GhotWhpLsKtVP0/i6.Nh9.fuY73cWjLoJjb2sKT8KISBcUW5q",
|
|
"BOB_PASS": "$2a$11$dZM98SpGeI7dCFFGSpt.JObQcix8YHml4TBUZoge9R1uxnMIln5ly",
|
|
"users": []interface{}{
|
|
map[string]interface{}{
|
|
"user": "alice",
|
|
"password": "$2a$10$UHR6GhotWhpLsKtVP0/i6.Nh9.fuY73cWjLoJjb2sKT8KISBcUW5q"},
|
|
map[string]interface{}{
|
|
"user": "bob",
|
|
"password": "$2a$11$dZM98SpGeI7dCFFGSpt.JObQcix8YHml4TBUZoge9R1uxnMIln5ly"},
|
|
},
|
|
"timeout": float64(0.5),
|
|
},
|
|
}
|
|
|
|
m, err := ParseFile("simple.conf")
|
|
if err != nil {
|
|
t.Fatalf("Received err: %v\n", err)
|
|
}
|
|
if m == nil {
|
|
t.Fatal("Received nil map")
|
|
}
|
|
|
|
if !reflect.DeepEqual(m, ex) {
|
|
t.Fatalf("Not Equal:\nReceived: '%+v'\nExpected: '%+v'\n", m, ex)
|
|
}
|
|
}
|
|
|
|
var varIncludedVariablesSample = `
|
|
authorization {
|
|
|
|
include "./includes/passwords.conf"
|
|
|
|
CAROL_PASS: foo
|
|
|
|
users = [
|
|
{user: alice, password: $ALICE_PASS}
|
|
{user: bob, password: $BOB_PASS}
|
|
{user: carol, password: $CAROL_PASS}
|
|
]
|
|
}
|
|
`
|
|
|
|
func TestIncludeVariablesWithChecks(t *testing.T) {
|
|
p, err := parse(varIncludedVariablesSample, "", true)
|
|
if err != nil {
|
|
t.Fatalf("Received err: %v\n", err)
|
|
}
|
|
key := "authorization"
|
|
m, ok := p.mapping[key]
|
|
if !ok {
|
|
t.Errorf("Expected %q to be in the config", key)
|
|
}
|
|
expectKeyVal := func(t *testing.T, m interface{}, expectedKey string, expectedVal string, expectedLine, expectedPos int) {
|
|
t.Helper()
|
|
tk := m.(*token)
|
|
v := tk.Value()
|
|
vv := v.(map[string]interface{})
|
|
value, ok := vv[expectedKey]
|
|
if !ok {
|
|
t.Errorf("Expected key %q", expectedKey)
|
|
}
|
|
tk, ok = value.(*token)
|
|
if !ok {
|
|
t.Fatalf("Expected token %v", value)
|
|
}
|
|
if tk.Line() != expectedLine {
|
|
t.Errorf("Expected token to be at line %d, got: %d", expectedLine, tk.Line())
|
|
}
|
|
if tk.Position() != expectedPos {
|
|
t.Errorf("Expected token to be at position %d, got: %d", expectedPos, tk.Position())
|
|
}
|
|
v = tk.Value()
|
|
if v != expectedVal {
|
|
t.Errorf("Expected %q, got: %s", expectedVal, v)
|
|
}
|
|
}
|
|
expectKeyVal(t, m, "ALICE_PASS", "$2a$10$UHR6GhotWhpLsKtVP0/i6.Nh9.fuY73cWjLoJjb2sKT8KISBcUW5q", 2, 1)
|
|
expectKeyVal(t, m, "BOB_PASS", "$2a$11$dZM98SpGeI7dCFFGSpt.JObQcix8YHml4TBUZoge9R1uxnMIln5ly", 3, 1)
|
|
expectKeyVal(t, m, "CAROL_PASS", "foo", 6, 3)
|
|
}
|