diff --git a/caddytest/caddytest.go b/caddytest/caddytest.go index 059b3e17..1dda345f 100644 --- a/caddytest/caddytest.go +++ b/caddytest/caddytest.go @@ -321,13 +321,13 @@ func (tc *Tester) AssertRedirect(requestURI string, expectedToLocation string, e return resp } -// AssertAdapt adapts a config and then tests it against an expected result -func AssertAdapt(t *testing.T, rawConfig string, adapterName string, expectedResponse string) { +// CompareAdapt adapts a config and then compares it against an expected result +func CompareAdapt(t *testing.T, rawConfig string, adapterName string, expectedResponse string) bool { cfgAdapter := caddyconfig.GetAdapter(adapterName) if cfgAdapter == nil { - t.Errorf("unrecognized config adapter '%s'", adapterName) - return + t.Logf("unrecognized config adapter '%s'", adapterName) + return false } options := make(map[string]interface{}) @@ -335,8 +335,8 @@ func AssertAdapt(t *testing.T, rawConfig string, adapterName string, expectedRes result, warnings, err := cfgAdapter.Adapt([]byte(rawConfig), options) if err != nil { - t.Errorf("adapting config using %s adapter: %v", adapterName, err) - return + t.Logf("adapting config using %s adapter: %v", adapterName, err) + return false } if len(warnings) > 0 { @@ -369,6 +369,15 @@ func AssertAdapt(t *testing.T, rawConfig string, adapterName string, expectedRes fmt.Printf(" + %s\n", d.Payload) } } + return false + } + return true +} + +// AssertAdapt adapts a config and then tests it against an expected result +func AssertAdapt(t *testing.T, rawConfig string, adapterName string, expectedResponse string) { + ok := CompareAdapt(t, rawConfig, adapterName, expectedResponse) + if !ok { t.Fail() } } diff --git a/caddytest/integration/caddyfile_adapt/global_options.txt b/caddytest/integration/caddyfile_adapt/global_options.txt new file mode 100644 index 00000000..33836ff7 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/global_options.txt @@ -0,0 +1,71 @@ +{ + debug + http_port 8080 + https_port 8443 + default_sni localhost + order root first + storage file_system { + root /data + } + acme_ca https://example.com + acme_ca_root /path/to/ca.crt + email test@example.com + admin off + on_demand_tls { + ask https://example.com + interval 30s + burst 20 + } + local_certs + key_type ed25519 +} + +:80 +---------- +{ + "admin": { + "disabled": true + }, + "logging": { + "logs": { + "default": { + "level": "DEBUG" + } + } + }, + "storage": { + "module": "file_system", + "root": "/data" + }, + "apps": { + "http": { + "http_port": 8080, + "https_port": 8443, + "servers": { + "srv0": { + "listen": [ + ":80" + ] + } + } + }, + "tls": { + "automation": { + "policies": [ + { + "issuer": { + "module": "internal" + } + } + ], + "on_demand": { + "rate_limit": { + "interval": 30000000000, + "burst": 20 + }, + "ask": "https://example.com" + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/http_only_on_any_address.txt b/caddytest/integration/caddyfile_adapt/http_only_on_any_address.txt new file mode 100644 index 00000000..8af2c333 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/http_only_on_any_address.txt @@ -0,0 +1,37 @@ +:80 { + respond /version 200 { + body "hello from localhost" + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "path": [ + "/version" + ] + } + ], + "handle": [ + { + "body": "hello from localhost", + "handler": "static_response", + "status_code": 200 + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/http_only_on_domain.txt b/caddytest/integration/caddyfile_adapt/http_only_on_domain.txt new file mode 100644 index 00000000..83e77598 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/http_only_on_domain.txt @@ -0,0 +1,59 @@ +http://a.caddy.localhost { + respond /version 200 { + body "hello from localhost" + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "host": [ + "a.caddy.localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "hello from localhost", + "handler": "static_response", + "status_code": 200 + } + ], + "match": [ + { + "path": [ + "/version" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ], + "automatic_https": { + "skip": [ + "a.caddy.localhost" + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/http_only_on_localhost.txt b/caddytest/integration/caddyfile_adapt/http_only_on_localhost.txt new file mode 100644 index 00000000..13326f65 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/http_only_on_localhost.txt @@ -0,0 +1,54 @@ +localhost:80 { + respond /version 200 { + body "hello from localhost" + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "host": [ + "localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "hello from localhost", + "handler": "static_response", + "status_code": 200 + } + ], + "match": [ + { + "path": [ + "/version" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/http_only_on_non_standard_port.txt b/caddytest/integration/caddyfile_adapt/http_only_on_non_standard_port.txt new file mode 100644 index 00000000..65d86bbe --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/http_only_on_non_standard_port.txt @@ -0,0 +1,59 @@ +http://a.caddy.localhost:81 { + respond /version 200 { + body "hello from localhost" + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":81" + ], + "routes": [ + { + "match": [ + { + "host": [ + "a.caddy.localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "hello from localhost", + "handler": "static_response", + "status_code": 200 + } + ], + "match": [ + { + "path": [ + "/version" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ], + "automatic_https": { + "skip": [ + "a.caddy.localhost" + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/https_on_domain.txt b/caddytest/integration/caddyfile_adapt/https_on_domain.txt new file mode 100644 index 00000000..fc584c53 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/https_on_domain.txt @@ -0,0 +1,54 @@ +a.caddy.localhost { + respond /version 200 { + body "hello from localhost" + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":443" + ], + "routes": [ + { + "match": [ + { + "host": [ + "a.caddy.localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "hello from localhost", + "handler": "static_response", + "status_code": 200 + } + ], + "match": [ + { + "path": [ + "/version" + ] + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/log_roll_days.txt b/caddytest/integration/caddyfile_adapt/log_roll_days.txt new file mode 100644 index 00000000..2d146f9c --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/log_roll_days.txt @@ -0,0 +1,47 @@ +:80 + +log { + output file /var/log/access.log { + roll_size 1gb + roll_keep 5 + roll_keep_for 90d + } +} +---------- +{ + "logging": { + "logs": { + "default": { + "exclude": [ + "http.log.access.log0" + ] + }, + "log0": { + "writer": { + "filename": "/var/log/access.log", + "output": "file", + "roll_keep": 5, + "roll_keep_days": 90, + "roll_size_mb": 954 + }, + "include": [ + "http.log.access.log0" + ] + } + } + }, + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "logs": { + "default_logger_name": "log0" + } + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/matcher_syntax.txt b/caddytest/integration/caddyfile_adapt/matcher_syntax.txt new file mode 100644 index 00000000..8cabc582 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/matcher_syntax.txt @@ -0,0 +1,77 @@ +:80 { + @matcher { + method GET + } + respond @matcher "get" + + @matcher2 method POST + respond @matcher2 "post" + + @matcher3 not method PUT + respond @matcher3 "not put" +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "method": [ + "GET" + ] + } + ], + "handle": [ + { + "body": "get", + "handler": "static_response" + } + ] + }, + { + "match": [ + { + "method": [ + "POST" + ] + } + ], + "handle": [ + { + "body": "post", + "handler": "static_response" + } + ] + }, + { + "match": [ + { + "not": [ + { + "method": [ + "PUT" + ] + } + ] + } + ], + "handle": [ + { + "body": "not put", + "handler": "static_response" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/not_block_merging.txt b/caddytest/integration/caddyfile_adapt/not_block_merging.txt new file mode 100644 index 00000000..c41a7496 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/not_block_merging.txt @@ -0,0 +1,49 @@ +:80 + +@test { + not { + header Abc "123" + header Bcd "123" + } +} +respond @test 403 +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "not": [ + { + "header": { + "Abc": [ + "123" + ], + "Bcd": [ + "123" + ] + } + } + ] + } + ], + "handle": [ + { + "handler": "static_response", + "status_code": 403 + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/shorthand_parameterized_placeholders.txt b/caddytest/integration/caddyfile_adapt/shorthand_parameterized_placeholders.txt new file mode 100644 index 00000000..d5c35b3c --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/shorthand_parameterized_placeholders.txt @@ -0,0 +1,43 @@ +localhost:80 +respond * "{header.content-type} {labels.0} {query.p} {path.0} {re.name.0}" +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "host": [ + "localhost" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "{http.request.header.content-type} {http.request.host.labels.0} {http.request.uri.query.p} {http.request.uri.path.0} {http.regexp.name.0}", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt_test.go b/caddytest/integration/caddyfile_adapt_test.go index 280e22ea..bfe22ada 100644 --- a/caddytest/integration/caddyfile_adapt_test.go +++ b/caddytest/integration/caddyfile_adapt_test.go @@ -1,587 +1,47 @@ package integration import ( + "io/ioutil" + "regexp" + "strings" "testing" "github.com/caddyserver/caddy/v2/caddytest" ) -func TestHttpOnlyOnLocalhost(t *testing.T) { - caddytest.AssertAdapt(t, ` - localhost:80 { - respond /version 200 { - body "hello from localhost" +func TestCaddyfileAdaptToJSON(t *testing.T) { + // load the list of test files from the dir + files, err := ioutil.ReadDir("./caddyfile_adapt") + if err != nil { + t.Errorf("failed to read caddyfile_adapt dir: %s", err) + } + + // prep a regexp to fix strings on windows + winNewlines := regexp.MustCompile(`\r?\n`) + + for _, f := range files { + if f.IsDir() { + continue + } + + // read the test file + filename := f.Name() + data, err := ioutil.ReadFile("./caddyfile_adapt/" + filename) + if err != nil { + t.Errorf("failed to read %s dir: %s", filename, err) + } + + // split the Caddyfile (first) and JSON (second) parts + parts := strings.Split(string(data), "----------") + caddyfile, json := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]) + + // replace windows newlines in the json with unix newlines + json = winNewlines.ReplaceAllString(json, "\n") + + // run the test + ok := caddytest.CompareAdapt(t, caddyfile, "caddyfile", json) + if !ok { + t.Errorf("failed to adapt %s", filename) } } - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":80" - ], - "routes": [ - { - "match": [ - { - "host": [ - "localhost" - ] - } - ], - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "body": "hello from localhost", - "handler": "static_response", - "status_code": 200 - } - ], - "match": [ - { - "path": [ - "/version" - ] - } - ] - } - ] - } - ], - "terminal": true - } - ] - } - } - } - } -}`) -} - -func TestHttpOnlyOnAnyAddress(t *testing.T) { - caddytest.AssertAdapt(t, ` - :80 { - respond /version 200 { - body "hello from localhost" - } - } - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":80" - ], - "routes": [ - { - "match": [ - { - "path": [ - "/version" - ] - } - ], - "handle": [ - { - "body": "hello from localhost", - "handler": "static_response", - "status_code": 200 - } - ] - } - ] - } - } - } - } -}`) -} - -func TestHttpsOnDomain(t *testing.T) { - caddytest.AssertAdapt(t, ` - a.caddy.localhost { - respond /version 200 { - body "hello from localhost" - } - } - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":443" - ], - "routes": [ - { - "match": [ - { - "host": [ - "a.caddy.localhost" - ] - } - ], - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "body": "hello from localhost", - "handler": "static_response", - "status_code": 200 - } - ], - "match": [ - { - "path": [ - "/version" - ] - } - ] - } - ] - } - ], - "terminal": true - } - ] - } - } - } - } -}`) -} - -func TestHttpOnlyOnDomain(t *testing.T) { - caddytest.AssertAdapt(t, ` - http://a.caddy.localhost { - respond /version 200 { - body "hello from localhost" - } - } - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":80" - ], - "routes": [ - { - "match": [ - { - "host": [ - "a.caddy.localhost" - ] - } - ], - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "body": "hello from localhost", - "handler": "static_response", - "status_code": 200 - } - ], - "match": [ - { - "path": [ - "/version" - ] - } - ] - } - ] - } - ], - "terminal": true - } - ], - "automatic_https": { - "skip": [ - "a.caddy.localhost" - ] - } - } - } - } - } -}`) -} - -func TestHttpOnlyOnNonStandardPort(t *testing.T) { - caddytest.AssertAdapt(t, ` - http://a.caddy.localhost:81 { - respond /version 200 { - body "hello from localhost" - } - } - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":81" - ], - "routes": [ - { - "match": [ - { - "host": [ - "a.caddy.localhost" - ] - } - ], - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "body": "hello from localhost", - "handler": "static_response", - "status_code": 200 - } - ], - "match": [ - { - "path": [ - "/version" - ] - } - ] - } - ] - } - ], - "terminal": true - } - ], - "automatic_https": { - "skip": [ - "a.caddy.localhost" - ] - } - } - } - } - } -}`) -} - -func TestMatcherSyntax(t *testing.T) { - caddytest.AssertAdapt(t, ` - :80 { - @matcher { - method GET - } - respond @matcher "get" - - @matcher2 method POST - respond @matcher2 "post" - - @matcher3 not method PUT - respond @matcher3 "not put" - } - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":80" - ], - "routes": [ - { - "match": [ - { - "method": [ - "GET" - ] - } - ], - "handle": [ - { - "body": "get", - "handler": "static_response" - } - ] - }, - { - "match": [ - { - "method": [ - "POST" - ] - } - ], - "handle": [ - { - "body": "post", - "handler": "static_response" - } - ] - }, - { - "match": [ - { - "not": [ - { - "method": [ - "PUT" - ] - } - ] - } - ], - "handle": [ - { - "body": "not put", - "handler": "static_response" - } - ] - } - ] - } - } - } - } -}`) -} - -func TestNotBlockMerging(t *testing.T) { - caddytest.AssertAdapt(t, ` - :80 - - @test { - not { - header Abc "123" - header Bcd "123" - } - } - respond @test 403 - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":80" - ], - "routes": [ - { - "match": [ - { - "not": [ - { - "header": { - "Abc": [ - "123" - ], - "Bcd": [ - "123" - ] - } - } - ] - } - ], - "handle": [ - { - "handler": "static_response", - "status_code": 403 - } - ] - } - ] - } - } - } - } -}`) -} - -func TestGlobalOptions(t *testing.T) { - caddytest.AssertAdapt(t, ` - { - debug - http_port 8080 - https_port 8443 - default_sni localhost - order root first - storage file_system { - root /data - } - acme_ca https://example.com - acme_ca_root /path/to/ca.crt - email test@example.com - admin off - on_demand_tls { - ask https://example.com - interval 30s - burst 20 - } - local_certs - key_type ed25519 - } - - :80 - `, "caddyfile", `{ - "admin": { - "disabled": true - }, - "logging": { - "logs": { - "default": { - "level": "DEBUG" - } - } - }, - "storage": { - "module": "file_system", - "root": "/data" - }, - "apps": { - "http": { - "http_port": 8080, - "https_port": 8443, - "servers": { - "srv0": { - "listen": [ - ":80" - ] - } - } - }, - "tls": { - "automation": { - "policies": [ - { - "issuer": { - "module": "internal" - } - } - ], - "on_demand": { - "rate_limit": { - "interval": 30000000000, - "burst": 20 - }, - "ask": "https://example.com" - } - } - } - } -}`) -} - -func TestLogRollDays(t *testing.T) { - caddytest.AssertAdapt(t, ` - :80 - - log { - output file /var/log/access.log { - roll_size 1gb - roll_keep 5 - roll_keep_for 90d - } - } - `, "caddyfile", `{ - "logging": { - "logs": { - "default": { - "exclude": [ - "http.log.access.log0" - ] - }, - "log0": { - "writer": { - "filename": "/var/log/access.log", - "output": "file", - "roll_keep": 5, - "roll_keep_days": 90, - "roll_size_mb": 954 - }, - "include": [ - "http.log.access.log0" - ] - } - } - }, - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":80" - ], - "logs": { - "default_logger_name": "log0" - } - } - } - } - } -}`) -} - -func TestShorthandParameterizedPlaceholders(t *testing.T) { - caddytest.AssertAdapt(t, ` - localhost:80 - respond * "{header.content-type} {labels.0} {query.p} {path.0} {re.name.0}" - `, "caddyfile", `{ - "apps": { - "http": { - "servers": { - "srv0": { - "listen": [ - ":80" - ], - "routes": [ - { - "match": [ - { - "host": [ - "localhost" - ] - } - ], - "handle": [ - { - "handler": "subroute", - "routes": [ - { - "handle": [ - { - "body": "{http.request.header.content-type} {http.request.host.labels.0} {http.request.uri.query.p} {http.request.uri.path.0} {http.regexp.name.0}", - "handler": "static_response" - } - ] - } - ] - } - ], - "terminal": true - } - ] - } - } - } - } -}`) }