mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-01 21:24:23 +08:00
383 lines
8.6 KiB
Go
383 lines
8.6 KiB
Go
package parse
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestStandardAddress(t *testing.T) {
|
|
for i, test := range []struct {
|
|
input string
|
|
host, port string
|
|
shouldErr bool
|
|
}{
|
|
{`localhost`, "localhost", "", false},
|
|
{`localhost:1234`, "localhost", "1234", false},
|
|
{`localhost:`, "localhost", "", false},
|
|
{`0.0.0.0`, "0.0.0.0", "", false},
|
|
{`127.0.0.1:1234`, "127.0.0.1", "1234", false},
|
|
{`:1234`, "", "1234", false},
|
|
{`[::1]`, "::1", "", false},
|
|
{`[::1]:1234`, "::1", "1234", false},
|
|
{`:`, "", "", false},
|
|
{`localhost:http`, "localhost", "http", false},
|
|
{`localhost:https`, "localhost", "https", false},
|
|
{`:http`, "", "http", false},
|
|
{`:https`, "", "https", false},
|
|
{`http://localhost`, "localhost", "http", false},
|
|
{`https://localhost`, "localhost", "https", false},
|
|
{`http://127.0.0.1`, "127.0.0.1", "http", false},
|
|
{`https://127.0.0.1`, "127.0.0.1", "https", false},
|
|
{`http://[::1]`, "::1", "http", false},
|
|
{`http://localhost:1234`, "localhost", "1234", false},
|
|
{`https://127.0.0.1:1234`, "127.0.0.1", "1234", false},
|
|
{`http://[::1]:1234`, "::1", "1234", false},
|
|
{``, "", "", false},
|
|
{`::1`, "::1", "", true},
|
|
{`localhost::`, "localhost::", "", true},
|
|
{`#$%@`, "#$%@", "", true},
|
|
} {
|
|
host, port, err := standardAddress(test.input)
|
|
|
|
if err != nil && !test.shouldErr {
|
|
t.Errorf("Test %d: Expected no error, but had error: %v", i, err)
|
|
}
|
|
if err == nil && test.shouldErr {
|
|
t.Errorf("Test %d: Expected error, but had none", i)
|
|
}
|
|
|
|
if host != test.host {
|
|
t.Errorf("Test %d: Expected host '%s', got '%s'", i, test.host, host)
|
|
}
|
|
|
|
if port != test.port {
|
|
t.Errorf("Test %d: Expected port '%s', got '%s'", i, test.port, port)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseOneAndImport(t *testing.T) {
|
|
setupParseTests()
|
|
|
|
testParseOne := func(input string) (multiServerBlock, error) {
|
|
p := testParser(input)
|
|
p.Next()
|
|
err := p.parseOne()
|
|
return p.block, err
|
|
}
|
|
|
|
for i, test := range []struct {
|
|
input string
|
|
shouldErr bool
|
|
addresses []address
|
|
tokens map[string]int // map of directive name to number of tokens expected
|
|
}{
|
|
{`localhost`, false, []address{
|
|
{"localhost", ""},
|
|
}, map[string]int{}},
|
|
|
|
{`localhost
|
|
dir1`, false, []address{
|
|
{"localhost", ""},
|
|
}, map[string]int{
|
|
"dir1": 1,
|
|
}},
|
|
|
|
{`localhost:1234
|
|
dir1 foo bar`, false, []address{
|
|
{"localhost", "1234"},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
}},
|
|
|
|
{`localhost {
|
|
dir1
|
|
}`, false, []address{
|
|
{"localhost", ""},
|
|
}, map[string]int{
|
|
"dir1": 1,
|
|
}},
|
|
|
|
{`localhost:1234 {
|
|
dir1 foo bar
|
|
dir2
|
|
}`, false, []address{
|
|
{"localhost", "1234"},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
"dir2": 1,
|
|
}},
|
|
|
|
{`http://localhost https://localhost
|
|
dir1 foo bar`, false, []address{
|
|
{"localhost", "http"},
|
|
{"localhost", "https"},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
}},
|
|
|
|
{`http://localhost https://localhost {
|
|
dir1 foo bar
|
|
}`, false, []address{
|
|
{"localhost", "http"},
|
|
{"localhost", "https"},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
}},
|
|
|
|
{`http://localhost, https://localhost {
|
|
dir1 foo bar
|
|
}`, false, []address{
|
|
{"localhost", "http"},
|
|
{"localhost", "https"},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
}},
|
|
|
|
{`http://localhost, {
|
|
}`, true, []address{
|
|
{"localhost", "http"},
|
|
}, map[string]int{}},
|
|
|
|
{`host1:80, http://host2.com
|
|
dir1 foo bar
|
|
dir2 baz`, false, []address{
|
|
{"host1", "80"},
|
|
{"host2.com", "http"},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
"dir2": 2,
|
|
}},
|
|
|
|
{`http://host1.com,
|
|
http://host2.com,
|
|
https://host3.com`, false, []address{
|
|
{"host1.com", "http"},
|
|
{"host2.com", "http"},
|
|
{"host3.com", "https"},
|
|
}, map[string]int{}},
|
|
|
|
{`http://host1.com:1234, https://host2.com
|
|
dir1 foo {
|
|
bar baz
|
|
}
|
|
dir2`, false, []address{
|
|
{"host1.com", "1234"},
|
|
{"host2.com", "https"},
|
|
}, map[string]int{
|
|
"dir1": 6,
|
|
"dir2": 1,
|
|
}},
|
|
|
|
{`127.0.0.1
|
|
dir1 {
|
|
bar baz
|
|
}
|
|
dir2 {
|
|
foo bar
|
|
}`, false, []address{
|
|
{"127.0.0.1", ""},
|
|
}, map[string]int{
|
|
"dir1": 5,
|
|
"dir2": 5,
|
|
}},
|
|
|
|
{`127.0.0.1
|
|
unknown_directive`, true, []address{
|
|
{"127.0.0.1", ""},
|
|
}, map[string]int{}},
|
|
|
|
{`localhost
|
|
dir1 {
|
|
foo`, true, []address{
|
|
{"localhost", ""},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
}},
|
|
|
|
{`localhost
|
|
dir1 {
|
|
}`, false, []address{
|
|
{"localhost", ""},
|
|
}, map[string]int{
|
|
"dir1": 3,
|
|
}},
|
|
|
|
{`localhost
|
|
dir1 {
|
|
nested {
|
|
foo
|
|
}
|
|
}
|
|
dir2 foo bar`, false, []address{
|
|
{"localhost", ""},
|
|
}, map[string]int{
|
|
"dir1": 7,
|
|
"dir2": 3,
|
|
}},
|
|
|
|
{``, false, []address{}, map[string]int{}},
|
|
|
|
{`localhost
|
|
dir1 arg1
|
|
import import_test1.txt`, false, []address{
|
|
{"localhost", ""},
|
|
}, map[string]int{
|
|
"dir1": 2,
|
|
"dir2": 3,
|
|
"dir3": 1,
|
|
}},
|
|
|
|
{`import import_test2.txt`, false, []address{
|
|
{"host1", ""},
|
|
}, map[string]int{
|
|
"dir1": 1,
|
|
"dir2": 2,
|
|
}},
|
|
} {
|
|
result, err := testParseOne(test.input)
|
|
|
|
if test.shouldErr && err == nil {
|
|
t.Errorf("Test %d: Expected an error, but didn't get one", i)
|
|
}
|
|
if !test.shouldErr && err != nil {
|
|
t.Errorf("Test %d: Expected no error, but got: %v", i, err)
|
|
}
|
|
|
|
if len(result.addresses) != len(test.addresses) {
|
|
t.Errorf("Test %d: Expected %d addresses, got %d",
|
|
i, len(test.addresses), len(result.addresses))
|
|
continue
|
|
}
|
|
for j, addr := range result.addresses {
|
|
if addr.host != test.addresses[j].host {
|
|
t.Errorf("Test %d, address %d: Expected host to be '%s', but was '%s'",
|
|
i, j, test.addresses[j].host, addr.host)
|
|
}
|
|
if addr.port != test.addresses[j].port {
|
|
t.Errorf("Test %d, address %d: Expected port to be '%s', but was '%s'",
|
|
i, j, test.addresses[j].port, addr.port)
|
|
}
|
|
}
|
|
|
|
if len(result.tokens) != len(test.tokens) {
|
|
t.Errorf("Test %d: Expected %d directives, had %d",
|
|
i, len(test.tokens), len(result.tokens))
|
|
continue
|
|
}
|
|
for directive, tokens := range result.tokens {
|
|
if len(tokens) != test.tokens[directive] {
|
|
t.Errorf("Test %d, directive '%s': Expected %d tokens, counted %d",
|
|
i, directive, test.tokens[directive], len(tokens))
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseAll(t *testing.T) {
|
|
setupParseTests()
|
|
|
|
for i, test := range []struct {
|
|
input string
|
|
shouldErr bool
|
|
addresses []address // one per expected server block, in order
|
|
}{
|
|
{`localhost`, false, []address{
|
|
{"localhost", ""},
|
|
}},
|
|
|
|
{`localhost:1234`, false, []address{
|
|
{"localhost", "1234"},
|
|
}},
|
|
|
|
{`localhost:1234 {
|
|
}
|
|
localhost:2015 {
|
|
}`, false, []address{
|
|
{"localhost", "1234"},
|
|
{"localhost", "2015"},
|
|
}},
|
|
|
|
{`localhost:1234, http://host2`, false, []address{
|
|
{"localhost", "1234"},
|
|
{"host2", "http"},
|
|
}},
|
|
|
|
{`localhost:1234, http://host2,`, true, []address{}},
|
|
|
|
{`http://host1.com, http://host2.com {
|
|
}
|
|
https://host3.com, https://host4.com {
|
|
}`, false, []address{
|
|
{"host1.com", "http"},
|
|
{"host2.com", "http"},
|
|
{"host3.com", "https"},
|
|
{"host4.com", "https"},
|
|
}},
|
|
} {
|
|
p := testParser(test.input)
|
|
blocks, err := p.parseAll()
|
|
|
|
if test.shouldErr && err == nil {
|
|
t.Errorf("Test %d: Expected an error, but didn't get one", i)
|
|
}
|
|
if !test.shouldErr && err != nil {
|
|
t.Errorf("Test %d: Expected no error, but got: %v", i, err)
|
|
}
|
|
|
|
if len(blocks) != len(test.addresses) {
|
|
t.Errorf("Test %d: Expected %d server blocks, got %d",
|
|
i, len(test.addresses), len(blocks))
|
|
continue
|
|
}
|
|
for j, block := range blocks {
|
|
if block.Host != test.addresses[j].host {
|
|
t.Errorf("Test %d, block %d: Expected host to be '%s', but was '%s'",
|
|
i, j, test.addresses[j].host, block.Host)
|
|
}
|
|
if block.Port != test.addresses[j].port {
|
|
t.Errorf("Test %d, block %d: Expected port to be '%s', but was '%s'",
|
|
i, j, test.addresses[j].port, block.Port)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Exploding the server blocks that have more than one address should replicate/share tokens
|
|
p := testParser(`host1 {
|
|
dir1 foo bar
|
|
}
|
|
|
|
host2, host3 {
|
|
dir2 foo bar
|
|
dir3 foo {
|
|
bar
|
|
}
|
|
}`)
|
|
blocks, err := p.parseAll()
|
|
if err != nil {
|
|
t.Fatalf("Expected there to not be an error, but there was: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(blocks[1].Tokens, blocks[2].Tokens) {
|
|
t.Errorf("Expected host2 and host3 to have same tokens, but they didn't.\nhost2 Block: %v\nhost3 Block: %v",
|
|
blocks[1].Tokens, blocks[2].Tokens)
|
|
}
|
|
}
|
|
|
|
func setupParseTests() {
|
|
// Set up some bogus directives for testing
|
|
ValidDirectives = map[string]struct{}{
|
|
"dir1": struct{}{},
|
|
"dir2": struct{}{},
|
|
"dir3": struct{}{},
|
|
}
|
|
}
|
|
|
|
func testParser(input string) parser {
|
|
buf := strings.NewReader(input)
|
|
p := parser{Dispenser: NewDispenser("Test", buf)}
|
|
return p
|
|
}
|