From 8b224e1ca1d7998ca3ad3fd3f453813a97310a7c Mon Sep 17 00:00:00 2001 From: Piotr Galar Date: Thu, 6 Apr 2023 10:14:19 +0200 Subject: [PATCH] refactor: make sugar tests the default (#32) * refactor: make sugar tests the default * fix: check.Not * fix: clean up calls to Build * chore: go fmt * fix: content type header check in TestDAgPbConversion --- tests/t0109_gateway_web_redirects_test.go | 2 +- tests/t0113_gateway_symlink_test.go | 2 +- tests/t0114_gateway_subdomains_test.go | 10 +- tests/t0116_gateway_cache_test.go | 212 +++++++++++----------- tests/t0117_gateway_block_test.go | 4 +- tests/t0118_gateway_car_test.go | 2 +- tests/t0122_gateway_tar_test.go | 2 +- tests/t0123_gateway_json_cbor_test.go | 16 +- tooling/test/report.go | 4 +- tooling/test/sugar.go | 95 +++------- tooling/test/test.go | 117 ++++-------- 11 files changed, 189 insertions(+), 277 deletions(-) diff --git a/tests/t0109_gateway_web_redirects_test.go b/tests/t0109_gateway_web_redirects_test.go index acb8ed651..e5471acf0 100644 --- a/tests/t0109_gateway_web_redirects_test.go +++ b/tests/t0109_gateway_web_redirects_test.go @@ -305,7 +305,7 @@ func TestRedirectsFileSupport(t *testing.T) { } if specs.SubdomainGateway.IsEnabled() { - Run(t, unwrapTests(t, tests).Build()) + Run(t, unwrapTests(t, tests)) } else { t.Skip("subdomain gateway disabled") } diff --git a/tests/t0113_gateway_symlink_test.go b/tests/t0113_gateway_symlink_test.go index 3b75b1309..075903cd5 100644 --- a/tests/t0113_gateway_symlink_test.go +++ b/tests/t0113_gateway_symlink_test.go @@ -45,5 +45,5 @@ func TestGatewaySymlink(t *testing.T) { }, } - test.Run(t, tests.Build()) + test.Run(t, tests) } diff --git a/tests/t0114_gateway_subdomains_test.go b/tests/t0114_gateway_subdomains_test.go index 5000cb08d..83464b42e 100644 --- a/tests/t0114_gateway_subdomains_test.go +++ b/tests/t0114_gateway_subdomains_test.go @@ -22,10 +22,10 @@ func TestGatewaySubdomains(t *testing.T) { CIDv1_TOO_LONG := fixture.MustGetCid("hello-CIDv1_TOO_LONG") CIDWikipedia := "QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco" - tests := []CTest{} + tests := SugarTests{} // sugar: readable way to add more tests - with := func(moreTests []CTest) { + with := func(moreTests SugarTests) { tests = append(tests, moreTests...) } @@ -64,7 +64,7 @@ func TestGatewaySubdomains(t *testing.T) { We return body with HTTP 301 so existing cli scripts that use path-based gateway do not break (curl doesn't auto-redirect without passing -L; wget does not span across hostnames by default) - Context: https://github.com/ipfs/go-ipfs/issues/6975 + Context: https://github.com/ipfs/go-ipfs/issues/6975 `, IsEqual("hello\n"), ), @@ -376,7 +376,7 @@ func TestGatewaySubdomains(t *testing.T) { } } -func testGatewayWithManyProtocols(t *testing.T, label string, hint string, reqURL interface{}, expected ExpectBuilder) []CTest { +func testGatewayWithManyProtocols(t *testing.T, label string, hint string, reqURL interface{}, expected ExpectBuilder) SugarTests { t.Helper() baseURL := "" @@ -449,5 +449,5 @@ func testGatewayWithManyProtocols(t *testing.T, label string, hint string, reqUR ), Response: expected, }, - }.Build() + } } diff --git a/tests/t0116_gateway_cache_test.go b/tests/t0116_gateway_cache_test.go index 5aac5ee87..d236a841f 100644 --- a/tests/t0116_gateway_cache_test.go +++ b/tests/t0116_gateway_cache_test.go @@ -197,116 +197,116 @@ func TestGatewayCache(t *testing.T) { }, // The tests below require `ipnsId` to be set. /* - { - Name: "GET for /ipns/ unixfs dir listing succeeds", - Request: Request(). - Path("ipns/%s/root2/root3/", ipnsId), - Response: Expect(). - Status(200). - Headers( - Header("Cache-Control"). - IsEmpty(), - Header("X-Ipfs-Path"). - Equals("/ipns/%s/root2/root3", ipnsId), - Header("X-Ipfs-Roots"). - Equals("%s,%s,%s", fixture.MustGetCid(), fixture.MustGetCid("root2"), fixture.MustGetCid("root2", "root3")), - Header("Etag"). - Matches("DirIndex-.*_CID-%s", fixture.MustGetCid("root2", "root3")), - ), - }, - { - Name: "GET for /ipns/ unixfs dir with index.html succeeds", - Request: Request(). - Path("ipns/%s/root2/root3/root4/", ipnsId), - Response: Expect(). - Status(200). - Headers( - Header("Cache-Control"). - IsEmpty(), - Header("X-Ipfs-Path"). - Equals("/ipns/%s/root2/root3/root4/", ipnsId), - Header("X-Ipfs-Roots"). - Equals("%s,%s,%s,%s", fixture.MustGetCid(), fixture.MustGetCid("root2"), fixture.MustGetCid("root2", "root3"), fixture.MustGetCid("root2", "root3", "root4")), - Header("Etag"). - Matches("DirIndex-.*_CID-%s", fixture.MustGetCid("root2", "root3", "root4")), - ), - }, - { - Name: "GET for /ipns/ unixfs file succeeds", - Request: Request(). - Path("ipns/%s/root2/root3/root4/index.html", ipnsId), - Response: Expect(). - Status(200). - Headers( - Header("Cache-Control"). - Equals("public, max-age=29030400, immutable"), - Header("X-Ipfs-Path"). - Equals("/ipns/%s/root2/root3/root4/index.html", ipnsId), - Header("X-Ipfs-Roots"). - Equals("%s,%s,%s,%s,%s", fixture.MustGetCid(), fixture.MustGetCid("root2"), fixture.MustGetCid("root2", "root3"), fixture.MustGetCid("root2", "root3", "root4"), fixture.MustGetCid("root2", "root3", "root4", "index.html")), - Header("Etag"). - Equals("\"%s\"", fixture.MustGetCid("root2", "root3", "root4", "index.html")), - ), - }, - { - Name: "GET for /ipns/ unixfs dir as DAG-JSON succeeds", - Request: Request(). - Path("ipns/%s/root2/root3/root4/", ipnsId). - Query("format", "dag-json"), - Response: Expect(). - Status(200). - Headers( - Header("Cache-Control"). - Equals("public, max-age=29030400, immutable"), - ), - }, - { - Name: "GET for /ipns/ unixfs dir as JSON succeeds", - Request: Request(). - Path("ipns/%s/root2/root3/root4/", ipnsId). - Query("format", "json"), - Response: Expect(). - Status(200). - Headers( - Header("Cache-Control"). - Equals("public, max-age=29030400, immutable"), - ), - }, - { - Name: "GET for /ipns/ file with matching Etag in If-None-Match returns 304 Not Modified", - Request: Request(). - Path("ipns/%s/root2/root3/root4/index.html", ipnsId). - Headers( - Header("If-None-Match", fmt.Sprintf("\"%s\"", fixture.MustGetCid("root2", "root3", "root4", "index.html"))), - ), - Response: Expect(). - Status(304), - }, + { + Name: "GET for /ipns/ unixfs dir listing succeeds", + Request: Request(). + Path("ipns/%s/root2/root3/", ipnsId), + Response: Expect(). + Status(200). + Headers( + Header("Cache-Control"). + IsEmpty(), + Header("X-Ipfs-Path"). + Equals("/ipns/%s/root2/root3", ipnsId), + Header("X-Ipfs-Roots"). + Equals("%s,%s,%s", fixture.MustGetCid(), fixture.MustGetCid("root2"), fixture.MustGetCid("root2", "root3")), + Header("Etag"). + Matches("DirIndex-.*_CID-%s", fixture.MustGetCid("root2", "root3")), + ), + }, + { + Name: "GET for /ipns/ unixfs dir with index.html succeeds", + Request: Request(). + Path("ipns/%s/root2/root3/root4/", ipnsId), + Response: Expect(). + Status(200). + Headers( + Header("Cache-Control"). + IsEmpty(), + Header("X-Ipfs-Path"). + Equals("/ipns/%s/root2/root3/root4/", ipnsId), + Header("X-Ipfs-Roots"). + Equals("%s,%s,%s,%s", fixture.MustGetCid(), fixture.MustGetCid("root2"), fixture.MustGetCid("root2", "root3"), fixture.MustGetCid("root2", "root3", "root4")), + Header("Etag"). + Matches("DirIndex-.*_CID-%s", fixture.MustGetCid("root2", "root3", "root4")), + ), + }, + { + Name: "GET for /ipns/ unixfs file succeeds", + Request: Request(). + Path("ipns/%s/root2/root3/root4/index.html", ipnsId), + Response: Expect(). + Status(200). + Headers( + Header("Cache-Control"). + Equals("public, max-age=29030400, immutable"), + Header("X-Ipfs-Path"). + Equals("/ipns/%s/root2/root3/root4/index.html", ipnsId), + Header("X-Ipfs-Roots"). + Equals("%s,%s,%s,%s,%s", fixture.MustGetCid(), fixture.MustGetCid("root2"), fixture.MustGetCid("root2", "root3"), fixture.MustGetCid("root2", "root3", "root4"), fixture.MustGetCid("root2", "root3", "root4", "index.html")), + Header("Etag"). + Equals("\"%s\"", fixture.MustGetCid("root2", "root3", "root4", "index.html")), + ), + }, + { + Name: "GET for /ipns/ unixfs dir as DAG-JSON succeeds", + Request: Request(). + Path("ipns/%s/root2/root3/root4/", ipnsId). + Query("format", "dag-json"), + Response: Expect(). + Status(200). + Headers( + Header("Cache-Control"). + Equals("public, max-age=29030400, immutable"), + ), + }, + { + Name: "GET for /ipns/ unixfs dir as JSON succeeds", + Request: Request(). + Path("ipns/%s/root2/root3/root4/", ipnsId). + Query("format", "json"), + Response: Expect(). + Status(200). + Headers( + Header("Cache-Control"). + Equals("public, max-age=29030400, immutable"), + ), + }, + { + Name: "GET for /ipns/ file with matching Etag in If-None-Match returns 304 Not Modified", + Request: Request(). + Path("ipns/%s/root2/root3/root4/index.html", ipnsId). + Headers( + Header("If-None-Match", fmt.Sprintf("\"%s\"", fixture.MustGetCid("root2", "root3", "root4", "index.html"))), + ), + Response: Expect(). + Status(304), + }, */ // The tests below require `etag` to be set. /* - { - Name: "GET for /ipfs/ dir listing with matching strong Etag in If-None-Match returns 304 Not Modified", - Request: Request(). - Path("ipfs/%s/root2/root3/", fixture.MustGetCid()). - Headers( - Header("If-None-Match", fmt.Sprintf("\"%s\"", etag)), - ), - Response: Expect(). - Status(304), - }, - { - Name: "GET for /ipfs/ dir listing with matching strong Etag in If-None-Match returns 304 Not Modified", - Request: Request(). - Path("ipfs/%s/root2/root3/", fixture.MustGetCid()). - Headers( - Header("If-None-Match", fmt.Sprintf("W/\"%s\"", etag)), - ), - Response: Expect(). - Status(304), - }, + { + Name: "GET for /ipfs/ dir listing with matching strong Etag in If-None-Match returns 304 Not Modified", + Request: Request(). + Path("ipfs/%s/root2/root3/", fixture.MustGetCid()). + Headers( + Header("If-None-Match", fmt.Sprintf("\"%s\"", etag)), + ), + Response: Expect(). + Status(304), + }, + { + Name: "GET for /ipfs/ dir listing with matching strong Etag in If-None-Match returns 304 Not Modified", + Request: Request(). + Path("ipfs/%s/root2/root3/", fixture.MustGetCid()). + Headers( + Header("If-None-Match", fmt.Sprintf("W/\"%s\"", etag)), + ), + Response: Expect(). + Status(304), + }, */ - }.Build() + } Run(t, tests) } diff --git a/tests/t0117_gateway_block_test.go b/tests/t0117_gateway_block_test.go index 41abbcefc..de295c142 100644 --- a/tests/t0117_gateway_block_test.go +++ b/tests/t0117_gateway_block_test.go @@ -11,7 +11,7 @@ import ( func TestGatewayBlock(t *testing.T) { fixture := car.MustOpenUnixfsCar("t0117-gateway-block.car") - + tests := SugarTests{ { Name: "GET with format=raw param returns a raw block", @@ -118,7 +118,7 @@ func TestGatewayBlock(t *testing.T) { }), ), }, - }.Build() + } Run(t, tests) } diff --git a/tests/t0118_gateway_car_test.go b/tests/t0118_gateway_car_test.go index dcd124a5c..b33a70068 100644 --- a/tests/t0118_gateway_car_test.go +++ b/tests/t0118_gateway_car_test.go @@ -43,7 +43,7 @@ func TestGatewayCar(t *testing.T) { Equals("none"), ), }, - }.Build() + } Run(t, tests) } diff --git a/tests/t0122_gateway_tar_test.go b/tests/t0122_gateway_tar_test.go index 54eeb7ba7..1867d087a 100644 --- a/tests/t0122_gateway_tar_test.go +++ b/tests/t0122_gateway_tar_test.go @@ -185,5 +185,5 @@ func TestGatewayTar(t *testing.T) { }, } - Run(t, tests.Build()) + Run(t, tests) } diff --git a/tests/t0123_gateway_json_cbor_test.go b/tests/t0123_gateway_json_cbor_test.go index 67652a7ed..d6208f87f 100644 --- a/tests/t0123_gateway_json_cbor_test.go +++ b/tests/t0123_gateway_json_cbor_test.go @@ -62,7 +62,7 @@ func TestGatewayJsonCbor(t *testing.T) { }, } - test.Run(t, tests.Build()) + test.Run(t, tests) } // ## Reading UnixFS (data encoded with dag-pb codec) as DAG-CBOR and DAG-JSON @@ -210,8 +210,9 @@ func TestDAgPbConversion(t *testing.T) { Response: Expect(). Status(200). Headers( + // NOTE: kubo gateway returns "text/plain; charset=utf-8" for example Header("Content-Type"). - Equals("text/plain"), + Contains("text/plain"), Header("Content-Type"). Not().Contains("application/%s", row.Format), Header("Content-Type"). @@ -240,8 +241,9 @@ func TestDAgPbConversion(t *testing.T) { Response: Expect(). Status(200). Headers( + // NOTE: kubo gateway returns "text/plain; charset=utf-8" for example Header("Content-Type"). - Equals("text/plain"), + Contains("text/plain"), Header("Content-Type"). Not().Contains("application/%s", row.Format), Header("Content-Type"). @@ -252,7 +254,7 @@ func TestDAgPbConversion(t *testing.T) { }, } - test.Run(t, tests.Build()) + test.Run(t, tests) } } @@ -403,7 +405,7 @@ func TestPlainCodec(t *testing.T) { }, } - test.Run(t, tests.Build()) + test.Run(t, tests) } } @@ -492,7 +494,7 @@ func TestPathing(t *testing.T) { }, } - test.Run(t, tests.Build()) + test.Run(t, tests) } // ## NATIVE TESTS for DAG-JSON (0x0129) and DAG-CBOR (0x71): @@ -854,6 +856,6 @@ func TestNativeDag(t *testing.T) { */ } - test.Run(t, tests.Build()) + test.Run(t, tests) } } diff --git a/tooling/test/report.go b/tooling/test/report.go index 2fcbf928a..2fbf80d9e 100644 --- a/tooling/test/report.go +++ b/tooling/test/report.go @@ -13,7 +13,7 @@ type ReportInput struct { Req *http.Request Res *http.Response Err error - Test CTest + Test SugarTest } const TEMPLATE = ` @@ -35,7 +35,7 @@ Actual Response: {{.Res | dump}} ` -func report(t *testing.T, test CTest, req *http.Request, res *http.Response, err error) { +func report(t *testing.T, test SugarTest, req *http.Request, res *http.Response, err error) { input := ReportInput{ Req: req, Res: res, diff --git a/tooling/test/sugar.go b/tooling/test/sugar.go index 0a05ab393..3cb7f0196 100644 --- a/tooling/test/sugar.go +++ b/tooling/test/sugar.go @@ -8,14 +8,15 @@ import ( ) type RequestBuilder struct { - Method_ string - Path_ string - URL_ string - Proxy_ string - UseProxyTunnel bool - Headers_ map[string]string - DoNotFollowRedirects_ bool - Query_ url.Values + Method_ string `json:"method,omitempty"` + Path_ string `json:"path,omitempty"` + URL_ string `json:"url,omitempty"` + Proxy_ string `json:"proxy,omitempty"` + UseProxyTunnel_ bool `json:"useProxyTunnel,omitempty"` + Headers_ map[string]string `json:"headers,omitempty"` + DoNotFollowRedirects_ bool `json:"doNotFollowRedirects,omitempty"` + Query_ url.Values `json:"query,omitempty"` + Body_ []byte `json:"body,omitempty"` } func Request() RequestBuilder { @@ -52,7 +53,7 @@ func (r RequestBuilder) Proxy(path string, args ...any) RequestBuilder { } func (r RequestBuilder) WithProxyTunnel() RequestBuilder { - r.UseProxyTunnel = true + r.UseProxyTunnel_ = true return r } @@ -81,33 +82,16 @@ func (r RequestBuilder) Headers(hs ...HeaderBuilder) RequestBuilder { } for _, h := range hs { - r.Headers_[h.Key] = h.Value + r.Headers_[h.Key_] = h.Value_ } return r } -func (r RequestBuilder) Request() CRequest { - if r.URL_ != "" && r.Path_ != "" { - panic("Both 'URL' and 'Path' are set") - } - - return CRequest{ - Method: r.Method_, - Path: r.Path_, - URL: r.URL_, - Query: r.Query_, - Proxy: r.Proxy_, - UseProxyTunnel: r.UseProxyTunnel, - Headers: r.Headers_, - DoNotFollowRedirects: r.DoNotFollowRedirects_, - } -} - type ExpectBuilder struct { - StatusCode int - Headers_ []HeaderBuilder - Body_ interface{} + StatusCode_ int `json:"statusCode,omitempty"` + Headers_ []HeaderBuilder `json:"headers,omitempty"` + Body_ interface{} `json:"body,omitempty"` } func Expect() ExpectBuilder { @@ -115,7 +99,7 @@ func Expect() ExpectBuilder { } func (e ExpectBuilder) Status(statusCode int) ExpectBuilder { - e.StatusCode = statusCode + e.StatusCode_ = statusCode return e } @@ -175,37 +159,12 @@ func (e ExpectBuilder) BodyWithHint(hint string, body interface{}) ExpectBuilder return e } -func (e ExpectBuilder) Response() CResponse { - headers := make(map[string]interface{}) - - // TODO: detect collision in keys - for _, h := range e.Headers_ { - c := h.Check - - if h.Not_ { - c = check.Not(h.Check) - } - - if h.Hint_ != "" { - headers[h.Key] = check.WithHint(h.Hint_, c) - } else { - headers[h.Key] = c - } - } - - return CResponse{ - StatusCode: e.StatusCode, - Headers: headers, - Body: e.Body_, - } -} - type HeaderBuilder struct { - Key string - Value string - Check check.Check[string] - Hint_ string - Not_ bool + Key_ string `json:"key,omitempty"` + Value_ string `json:"value,omitempty"` + Check_ check.Check[string] `json:"check,omitempty"` + Hint_ string `json:"hint,omitempty"` + Not_ bool `json:"not,omitempty"` } func Header(key string, rest ...any) HeaderBuilder { @@ -213,23 +172,23 @@ func Header(key string, rest ...any) HeaderBuilder { // check if rest[0] is a string if value, ok := rest[0].(string); ok { value := fmt.Sprintf(value, rest[1:]...) - return HeaderBuilder{Key: key, Value: value, Check: check.IsEqual(value)} + return HeaderBuilder{Key_: key, Value_: value, Check_: check.IsEqual(value)} } else { panic("rest[0] must be a string") } } - return HeaderBuilder{Key: key} + return HeaderBuilder{Key_: key} } func (h HeaderBuilder) Contains(value string, rest ...any) HeaderBuilder { - h.Check = check.Contains(value, rest...) + h.Check_ = check.Contains(value, rest...) return h } func (h HeaderBuilder) Matches(value string, rest ...any) HeaderBuilder { - h.Check = check.Matches(value, rest...) + h.Check_ = check.Matches(value, rest...) return h } @@ -239,17 +198,17 @@ func (h HeaderBuilder) Hint(hint string) HeaderBuilder { } func (h HeaderBuilder) Equals(value string, args ...any) HeaderBuilder { - h.Check = check.IsEqual(value, args...) + h.Check_ = check.IsEqual(value, args...) return h } func (h HeaderBuilder) IsEmpty() HeaderBuilder { - h.Check = check.CheckIsEmpty{} + h.Check_ = check.CheckIsEmpty{} return h } func (h HeaderBuilder) Checks(f func(string) bool) HeaderBuilder { - h.Check = check.CheckFunc[string]{ + h.Check_ = check.CheckFunc[string]{ Fn: f, } return h diff --git a/tooling/test/test.go b/tooling/test/test.go index 1225ed1a1..388194bc3 100644 --- a/tooling/test/test.go +++ b/tooling/test/test.go @@ -5,38 +5,11 @@ import ( "fmt" "io" "net/http" - "net/url" "testing" "github.com/ipfs/gateway-conformance/tooling/check" ) -type CRequest struct { - Method string `json:"method,omitempty"` - URL string `json:"url,omitempty"` - Query url.Values `json:"query,omitempty"` - Proxy string `json:"proxy,omitempty"` - UseProxyTunnel bool `json:"useProxyTunnel,omitempty"` - DoNotFollowRedirects bool `json:"doNotFollowRedirects,omitempty"` - Path string `json:"path,omitempty"` - Subdomain string `json:"subdomain,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - Body []byte `json:"body,omitempty"` -} - -type CResponse struct { - StatusCode int `json:"statusCode,omitempty"` - Headers map[string]interface{} `json:"headers,omitempty"` - Body interface{} `json:"body,omitempty"` -} - -type CTest struct { - Name string `json:"name,omitempty"` - Hint string `json:"hint,omitempty"` - Request CRequest `json:"request,omitempty"` - Response CResponse `json:"response,omitempty"` -} - type SugarTest struct { Name string Hint string @@ -46,25 +19,12 @@ type SugarTest struct { type SugarTests []SugarTest -func (s SugarTests) Build() []CTest { - var tests []CTest - for _, test := range s { - tests = append(tests, CTest{ - Name: test.Name, - Hint: test.Hint, - Request: test.Request.Request(), - Response: test.Response.Response(), - }) - } - return tests -} - -func Run(t *testing.T, tests []CTest) { +func Run(t *testing.T, tests SugarTests) { // NewDialer() for _, test := range tests { t.Run(test.Name, func(t *testing.T) { - method := test.Request.Method + method := test.Request.Method_ if method == "" { method = "GET" } @@ -72,17 +32,17 @@ func Run(t *testing.T, tests []CTest) { // Prepare a client, // use proxy, deal with redirects, etc. client := &http.Client{} - if test.Request.UseProxyTunnel { - if test.Request.Proxy == "" { + if test.Request.UseProxyTunnel_ { + if test.Request.Proxy_ == "" { t.Fatal("ProxyTunnel requires a proxy") } - client = NewProxyTunnelClient(test.Request.Proxy) - } else if test.Request.Proxy != "" { - client = NewProxyClient(test.Request.Proxy) + client = NewProxyTunnelClient(test.Request.Proxy_) + } else if test.Request.Proxy_ != "" { + client = NewProxyClient(test.Request.Proxy_) } - if test.Request.DoNotFollowRedirects { + if test.Request.DoNotFollowRedirects_ { client.CheckRedirect = func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse } @@ -106,27 +66,27 @@ func Run(t *testing.T, tests []CTest) { } var url string - if test.Request.URL != "" && test.Request.Path != "" { + if test.Request.URL_ != "" && test.Request.Path_ != "" { localReport(t, "Both 'URL' and 'Path' are set") } - if test.Request.URL == "" && test.Request.Path == "" { + if test.Request.URL_ == "" && test.Request.Path_ == "" { localReport(t, "Neither 'URL' nor 'Path' are set") } - if test.Request.URL != "" { - url = test.Request.URL + if test.Request.URL_ != "" { + url = test.Request.URL_ } - if test.Request.Path != "" { - url = fmt.Sprintf("%s/%s", GatewayURL, test.Request.Path) + if test.Request.Path_ != "" { + url = fmt.Sprintf("%s/%s", GatewayURL, test.Request.Path_) } - query := test.Request.Query.Encode() + query := test.Request.Query_.Encode() if query != "" { url = fmt.Sprintf("%s?%s", url, query) } var body io.Reader - if test.Request.Body != nil { - body = bytes.NewBuffer(test.Request.Body) + if test.Request.Body_ != nil { + body = bytes.NewBuffer(test.Request.Body_) } // create a request @@ -136,7 +96,7 @@ func Run(t *testing.T, tests []CTest) { } // add headers - for key, value := range test.Request.Headers { + for key, value := range test.Request.Headers_ { req.Header.Add(key, value) // https://github.com/golang/go/issues/7682 @@ -152,41 +112,32 @@ func Run(t *testing.T, tests []CTest) { localReport(t, "Querying %s failed: %s", url, err) } - if test.Response.StatusCode != 0 { - if res.StatusCode != test.Response.StatusCode { - localReport(t, "Status code is not %d. It is %d", test.Response.StatusCode, res.StatusCode) + if test.Response.StatusCode_ != 0 { + if res.StatusCode != test.Response.StatusCode_ { + localReport(t, "Status code is not %d. It is %d", test.Response.StatusCode_, res.StatusCode) } } - for key, value := range test.Response.Headers { - t.Run(fmt.Sprintf("Header %s", key), func(t *testing.T) { - actual := res.Header.Get(key) - - var output check.CheckOutput - - switch v := value.(type) { - case check.Check[string]: - output = v.Check(actual) - case string: - output = check.IsEqual(v).Check(actual) - default: - output = check.CheckOutput{ - Success: false, - Reason: fmt.Sprintf("Header check '%s' has an invalid type: %T", key, value), - } + for _, header := range test.Response.Headers_ { + t.Run(fmt.Sprintf("Header %s", header.Key_), func(t *testing.T) { + actual := res.Header.Get(header.Key_) + c := header.Check_ + if header.Not_ { + c = check.Not(c) } + output := c.Check(actual) if !output.Success { - if output.Hint == "" { - localReport(t, "Header '%s' %s", key, output.Reason) + if header.Hint_ == "" { + localReport(t, "Header '%s' %s", header.Key_, output.Reason) } else { - localReport(t, "Header '%s' %s (%s)", key, output.Reason, output.Hint) + localReport(t, "Header '%s' %s (%s)", header.Key_, output.Reason, header.Hint_) } } }) } - if test.Response.Body != nil { + if test.Response.Body_ != nil { defer res.Body.Close() resBody, err := io.ReadAll(res.Body) if err != nil { @@ -195,7 +146,7 @@ func Run(t *testing.T, tests []CTest) { var output check.CheckOutput - switch v := test.Response.Body.(type) { + switch v := test.Response.Body_.(type) { case check.Check[string]: output = v.Check(string(resBody)) case check.Check[[]byte]: @@ -207,7 +158,7 @@ func Run(t *testing.T, tests []CTest) { default: output = check.CheckOutput{ Success: false, - Reason: fmt.Sprintf("Body check has an invalid type: %T", test.Response.Body), + Reason: fmt.Sprintf("Body check has an invalid type: %T", test.Response.Body_), } }