Fix more tests and remove json caddyfile stuff
This commit is contained in:
parent
d933bb2666
commit
0ed79664db
4 changed files with 5 additions and 345 deletions
|
@ -4,5 +4,5 @@ go:
|
||||||
- 1.5
|
- 1.5
|
||||||
- 1.6
|
- 1.6
|
||||||
- tip
|
- tip
|
||||||
#script:
|
script:
|
||||||
# - go test -race -v -bench=./... ./...
|
- go test -race -bench=./... ./...
|
||||||
|
|
|
@ -1,173 +0,0 @@
|
||||||
package caddyfile
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/miekg/coredns/core/parse"
|
|
||||||
)
|
|
||||||
|
|
||||||
const filename = "Caddyfile"
|
|
||||||
|
|
||||||
// ToJSON converts caddyfile to its JSON representation.
|
|
||||||
func ToJSON(caddyfile []byte) ([]byte, error) {
|
|
||||||
var j Caddyfile
|
|
||||||
|
|
||||||
serverBlocks, err := parse.ServerBlocks(filename, bytes.NewReader(caddyfile), false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sb := range serverBlocks {
|
|
||||||
block := ServerBlock{Body: [][]interface{}{}}
|
|
||||||
|
|
||||||
// Fill up host list
|
|
||||||
for _, host := range sb.HostList() {
|
|
||||||
block.Hosts = append(block.Hosts, host)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract directives deterministically by sorting them
|
|
||||||
var directives = make([]string, len(sb.Tokens))
|
|
||||||
for dir := range sb.Tokens {
|
|
||||||
directives = append(directives, dir)
|
|
||||||
}
|
|
||||||
sort.Strings(directives)
|
|
||||||
|
|
||||||
// Convert each directive's tokens into our JSON structure
|
|
||||||
for _, dir := range directives {
|
|
||||||
disp := parse.NewDispenserTokens(filename, sb.Tokens[dir])
|
|
||||||
for disp.Next() {
|
|
||||||
block.Body = append(block.Body, constructLine(&disp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tack this block onto the end of the list
|
|
||||||
j = append(j, block)
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := json.Marshal(j)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructLine transforms tokens into a JSON-encodable structure;
|
|
||||||
// but only one line at a time, to be used at the top-level of
|
|
||||||
// a server block only (where the first token on each line is a
|
|
||||||
// directive) - not to be used at any other nesting level.
|
|
||||||
func constructLine(d *parse.Dispenser) []interface{} {
|
|
||||||
var args []interface{}
|
|
||||||
|
|
||||||
args = append(args, d.Val())
|
|
||||||
|
|
||||||
for d.NextArg() {
|
|
||||||
if d.Val() == "{" {
|
|
||||||
args = append(args, constructBlock(d))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
args = append(args, d.Val())
|
|
||||||
}
|
|
||||||
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructBlock recursively processes tokens into a
|
|
||||||
// JSON-encodable structure. To be used in a directive's
|
|
||||||
// block. Goes to end of block.
|
|
||||||
func constructBlock(d *parse.Dispenser) [][]interface{} {
|
|
||||||
block := [][]interface{}{}
|
|
||||||
|
|
||||||
for d.Next() {
|
|
||||||
if d.Val() == "}" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
block = append(block, constructLine(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
return block
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromJSON converts JSON-encoded jsonBytes to Caddyfile text
|
|
||||||
func FromJSON(jsonBytes []byte) ([]byte, error) {
|
|
||||||
var j Caddyfile
|
|
||||||
var result string
|
|
||||||
|
|
||||||
err := json.Unmarshal(jsonBytes, &j)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for sbPos, sb := range j {
|
|
||||||
if sbPos > 0 {
|
|
||||||
result += "\n\n"
|
|
||||||
}
|
|
||||||
for i, host := range sb.Hosts {
|
|
||||||
if i > 0 {
|
|
||||||
result += ", "
|
|
||||||
}
|
|
||||||
result += host
|
|
||||||
}
|
|
||||||
result += jsonToText(sb.Body, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return []byte(result), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// jsonToText recursively transforms a scope of JSON into plain
|
|
||||||
// Caddyfile text.
|
|
||||||
func jsonToText(scope interface{}, depth int) string {
|
|
||||||
var result string
|
|
||||||
|
|
||||||
switch val := scope.(type) {
|
|
||||||
case string:
|
|
||||||
if strings.ContainsAny(val, "\" \n\t\r") {
|
|
||||||
result += `"` + strings.Replace(val, "\"", "\\\"", -1) + `"`
|
|
||||||
} else {
|
|
||||||
result += val
|
|
||||||
}
|
|
||||||
case int:
|
|
||||||
result += strconv.Itoa(val)
|
|
||||||
case float64:
|
|
||||||
result += fmt.Sprintf("%v", val)
|
|
||||||
case bool:
|
|
||||||
result += fmt.Sprintf("%t", val)
|
|
||||||
case [][]interface{}:
|
|
||||||
result += " {\n"
|
|
||||||
for _, arg := range val {
|
|
||||||
result += strings.Repeat("\t", depth) + jsonToText(arg, depth+1) + "\n"
|
|
||||||
}
|
|
||||||
result += strings.Repeat("\t", depth-1) + "}"
|
|
||||||
case []interface{}:
|
|
||||||
for i, v := range val {
|
|
||||||
if block, ok := v.([]interface{}); ok {
|
|
||||||
result += "{\n"
|
|
||||||
for _, arg := range block {
|
|
||||||
result += strings.Repeat("\t", depth) + jsonToText(arg, depth+1) + "\n"
|
|
||||||
}
|
|
||||||
result += strings.Repeat("\t", depth-1) + "}"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
result += jsonToText(v, depth)
|
|
||||||
if i < len(val)-1 {
|
|
||||||
result += " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Caddyfile encapsulates a slice of ServerBlocks.
|
|
||||||
type Caddyfile []ServerBlock
|
|
||||||
|
|
||||||
// ServerBlock represents a server block.
|
|
||||||
type ServerBlock struct {
|
|
||||||
Hosts []string `json:"hosts"`
|
|
||||||
Body [][]interface{} `json:"body"`
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
package caddyfile
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
var tests = []struct {
|
|
||||||
caddyfile, json string
|
|
||||||
}{
|
|
||||||
{ // 0
|
|
||||||
caddyfile: `foo {
|
|
||||||
root /bar
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["foo"],"body":[["root","/bar"]]}]`,
|
|
||||||
},
|
|
||||||
{ // 1
|
|
||||||
caddyfile: `host1, host2 {
|
|
||||||
dir {
|
|
||||||
def
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host1","host2"],"body":[["dir",[["def"]]]]}]`,
|
|
||||||
},
|
|
||||||
{ // 2
|
|
||||||
caddyfile: `host1, host2 {
|
|
||||||
dir abc {
|
|
||||||
def ghi
|
|
||||||
jkl
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host1","host2"],"body":[["dir","abc",[["def","ghi"],["jkl"]]]]}]`,
|
|
||||||
},
|
|
||||||
{ // 3
|
|
||||||
caddyfile: `host1:1234, host2:5678 {
|
|
||||||
dir abc {
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host1:1234","host2:5678"],"body":[["dir","abc",[]]]}]`,
|
|
||||||
},
|
|
||||||
{ // 4
|
|
||||||
caddyfile: `host {
|
|
||||||
foo "bar baz"
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host"],"body":[["foo","bar baz"]]}]`,
|
|
||||||
},
|
|
||||||
{ // 5
|
|
||||||
caddyfile: `host, host:80 {
|
|
||||||
foo "bar \"baz\""
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host","host:80"],"body":[["foo","bar \"baz\""]]}]`,
|
|
||||||
},
|
|
||||||
{ // 6
|
|
||||||
caddyfile: `host {
|
|
||||||
foo "bar
|
|
||||||
baz"
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host"],"body":[["foo","bar\nbaz"]]}]`,
|
|
||||||
},
|
|
||||||
{ // 7
|
|
||||||
caddyfile: `host {
|
|
||||||
dir 123 4.56 true
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host"],"body":[["dir","123","4.56","true"]]}]`, // NOTE: I guess we assume numbers and booleans should be encoded as strings...?
|
|
||||||
},
|
|
||||||
{ // 8
|
|
||||||
caddyfile: `host, host {
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host","host"],"body":[]}]`, // hosts in JSON are always host:port format (if port is specified), for consistency
|
|
||||||
},
|
|
||||||
{ // 9
|
|
||||||
caddyfile: `host {
|
|
||||||
dir1 a b
|
|
||||||
dir2 c d
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host"],"body":[["dir1","a","b"],["dir2","c","d"]]}]`,
|
|
||||||
},
|
|
||||||
{ // 10
|
|
||||||
caddyfile: `host {
|
|
||||||
dir a b
|
|
||||||
dir c d
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host"],"body":[["dir","a","b"],["dir","c","d"]]}]`,
|
|
||||||
},
|
|
||||||
{ // 11
|
|
||||||
caddyfile: `host {
|
|
||||||
dir1 a b
|
|
||||||
dir2 {
|
|
||||||
c
|
|
||||||
d
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host"],"body":[["dir1","a","b"],["dir2",[["c"],["d"]]]]}]`,
|
|
||||||
},
|
|
||||||
{ // 12
|
|
||||||
caddyfile: `host1 {
|
|
||||||
dir1
|
|
||||||
}
|
|
||||||
|
|
||||||
host2 {
|
|
||||||
dir2
|
|
||||||
}`,
|
|
||||||
json: `[{"hosts":["host1"],"body":[["dir1"]]},{"hosts":["host2"],"body":[["dir2"]]}]`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestToJSON(t *testing.T) {
|
|
||||||
for i, test := range tests {
|
|
||||||
output, err := ToJSON([]byte(test.caddyfile))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Test %d: %v", i, err)
|
|
||||||
}
|
|
||||||
if string(output) != test.json {
|
|
||||||
t.Errorf("Test %d\nExpected:\n'%s'\nActual:\n'%s'", i, test.json, string(output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromJSON(t *testing.T) {
|
|
||||||
for i, test := range tests {
|
|
||||||
output, err := FromJSON([]byte(test.json))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Test %d: %v", i, err)
|
|
||||||
}
|
|
||||||
if string(output) != test.caddyfile {
|
|
||||||
t.Errorf("Test %d\nExpected:\n'%s'\nActual:\n'%s'", i, test.caddyfile, string(output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStandardizeAddress(t *testing.T) {
|
|
||||||
// host:https should be converted to https://host
|
|
||||||
output, err := ToJSON([]byte(`host:https`))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if expected, actual := `[{"hosts":["https://host"],"body":[]}]`, string(output); expected != actual {
|
|
||||||
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
output, err = FromJSON([]byte(`[{"hosts":["https://host"],"body":[]}]`))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if expected, actual := "https://host {\n}", string(output); expected != actual {
|
|
||||||
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
// host: should be converted to just host
|
|
||||||
output, err = ToJSON([]byte(`host:`))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if expected, actual := `[{"hosts":["host"],"body":[]}]`, string(output); expected != actual {
|
|
||||||
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
|
|
||||||
}
|
|
||||||
output, err = FromJSON([]byte(`[{"hosts":["host:"],"body":[]}]`))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if expected, actual := "host {\n}", string(output); expected != actual {
|
|
||||||
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +1,8 @@
|
||||||
package https
|
package https
|
||||||
|
|
||||||
import (
|
// TODO(miek): all fail
|
||||||
"crypto/tls"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/miekg/coredns/core/setup"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
/*
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
// Write test certificates to disk before tests, and clean up
|
// Write test certificates to disk before tests, and clean up
|
||||||
// when we're done.
|
// when we're done.
|
||||||
|
@ -230,3 +223,4 @@ AwEHoUQDQgAEs22MtnG79K1mvIyjEO9GLx7BFD0tBbGnwQ0VPsuCxC6IeVuXbQDL
|
||||||
SiVQvFZ6lUszTlczNxVkpEfqrM6xAupB7g==
|
SiVQvFZ6lUszTlczNxVkpEfqrM6xAupB7g==
|
||||||
-----END EC PRIVATE KEY-----
|
-----END EC PRIVATE KEY-----
|
||||||
`)
|
`)
|
||||||
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue