mirror of
https://github.com/alibaba/higress.git
synced 2026-02-24 12:40:48 +08:00
1104 lines
33 KiB
Go
1104 lines
33 KiB
Go
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package http
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/alibaba/higress/test/e2e/conformance/utils/roundtripper"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCompareRequest(t *testing.T) {
|
|
cases := []struct {
|
|
caseName string
|
|
errMsg string
|
|
req *roundtripper.Request
|
|
cReq *roundtripper.CapturedRequest
|
|
cRes *roundtripper.CapturedResponse
|
|
expected Assertion
|
|
}{
|
|
{
|
|
caseName: "compare request header ok",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
Body: []byte(``),
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
Body: []byte(``),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(``),
|
|
ContentType: "",
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body ok",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/json"},
|
|
},
|
|
Body: map[string]interface{}{
|
|
"X-body-test1": []interface{}{"b1"},
|
|
"X-body-test2": []interface{}{"b2", "b22"},
|
|
},
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2","b22"]
|
|
}`),
|
|
ContentType: ContentTypeApplicationJson,
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body fail, because headers not consistent",
|
|
errMsg: "expected X-header-test1 header to be set to h1, got h1,hn",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1", "hn"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/json"},
|
|
},
|
|
Body: map[string]interface{}{
|
|
"X-body-test1": []interface{}{"b1"},
|
|
"X-body-test2": []interface{}{"b2", "b22"},
|
|
},
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2","b22"]
|
|
}`),
|
|
ContentType: ContentTypeApplicationJson,
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body fail, because body not consistent",
|
|
errMsg: "expected application/json body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/json"},
|
|
},
|
|
Body: map[string]interface{}{
|
|
"X-body-test1": []interface{}{"b1", "bn"},
|
|
"X-body-test2": []interface{}{"b2", "b22"},
|
|
},
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2","b22"]
|
|
}`),
|
|
ContentType: ContentTypeApplicationJson,
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body ok, body type is text/plain",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"text/plain"},
|
|
},
|
|
Body: "hello higress",
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`hello higress`),
|
|
ContentType: ContentTypeTextPlain,
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body fail, because body not consistent. body type is text/plain",
|
|
errMsg: "expected text/plain body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"text/plain"},
|
|
},
|
|
Body: "Hello Higress",
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`hello higress`),
|
|
ContentType: ContentTypeTextPlain,
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body ok, body type is FormUrlencoded",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/x-www-form-urlencoded"},
|
|
},
|
|
Body: map[string][]string{
|
|
"X-body-test1": {"b1"},
|
|
"X-body-test2": {"b2", "b22"},
|
|
},
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`X-body-test1=b1&X-body-test2=b2&X-body-test2=b22`),
|
|
ContentType: ContentTypeFormUrlencoded,
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body fail, because body not consistent, body type is FormUrlencoded",
|
|
errMsg: "expected application/x-www-form-urlencoded body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/x-www-form-urlencoded"},
|
|
},
|
|
Body: map[string][]string{
|
|
"X-body-test1": {"b1", "bn"},
|
|
"X-body-test2": {"b2", "b22"},
|
|
},
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`X-body-test1=b1&X-body-test2=b2&X-body-test2=b22`),
|
|
ContentType: ContentTypeFormUrlencoded,
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body ok, body type is MultipartForm",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"multipart/form-data; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd"},
|
|
},
|
|
Body: map[string][]string{
|
|
"name": {"denzel"},
|
|
"flag": {"test"},
|
|
},
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"file\"; filename=\"Screenshot.png\"\r\n" +
|
|
"Content-Type: image/png\r\n\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"name\"\r\n\r\n" +
|
|
"denzel\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"flag\"\r\n\r\n" +
|
|
"test\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd--\r\n"),
|
|
ContentType: ContentTypeMultipartForm + "; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd",
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare request header&body fail, because body not consistent. body type is MultipartForm",
|
|
errMsg: "expected multipart/form-data body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{
|
|
Path: "/",
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"multipart/form-data; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd"},
|
|
},
|
|
Body: map[string][]string{
|
|
"name": {"higress"},
|
|
"flag": {"test"},
|
|
},
|
|
Namespace: "",
|
|
Pod: "",
|
|
},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetRequest},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{
|
|
Host: "foo.com",
|
|
Method: "GET",
|
|
Path: "/",
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"file\"; filename=\"Screenshot.png\"\r\n" +
|
|
"Content-Type: image/png\r\n\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"name\"\r\n\r\n" +
|
|
"denzel\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"flag\"\r\n\r\n" +
|
|
"test\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd--\r\n"),
|
|
ContentType: ContentTypeMultipartForm + "; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd",
|
|
},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.caseName, func(t *testing.T) {
|
|
err := CompareRequest(c.req, c.cReq, c.cRes, c.expected)
|
|
if c.errMsg != "" {
|
|
require.ErrorContains(t, err, c.errMsg)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCompareResponse(t *testing.T) {
|
|
cases := []struct {
|
|
caseName string
|
|
errMsg string
|
|
req *roundtripper.Request
|
|
cReq *roundtripper.CapturedRequest
|
|
cRes *roundtripper.CapturedResponse
|
|
expected Assertion
|
|
}{
|
|
{
|
|
caseName: "compare response header ok",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
},
|
|
Body: []byte(``),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(``),
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body ok",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/json"},
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2", "b22"]
|
|
}`),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2","b22"]
|
|
}`),
|
|
ContentType: ContentTypeApplicationJson,
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body fail, because headers not consistent",
|
|
errMsg: "expected X-header-test1 header to be set to h1, got h1,hn",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1", "hn"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/json"},
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2", "b22"]
|
|
}`),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2","b22"]
|
|
}`),
|
|
ContentType: ContentTypeApplicationJson,
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body fail, because body not consistent",
|
|
errMsg: "expected application/json body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/json"},
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1", "bn"],
|
|
"X-body-test2":["b2", "b22"]
|
|
}`),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`
|
|
{
|
|
"X-body-test1":["b1"],
|
|
"X-body-test2":["b2","b22"]
|
|
}`),
|
|
ContentType: ContentTypeApplicationJson,
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body ok, body type is text/plain",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"text/plain"},
|
|
},
|
|
Body: []byte(`hello higress`),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`hello higress`),
|
|
ContentType: ContentTypeTextPlain,
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body fail, because body not consistent. body type is text/plain",
|
|
errMsg: "expected text/plain body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"text/plain"},
|
|
},
|
|
Body: []byte(`Hello Higress`),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`hello higress`),
|
|
ContentType: ContentTypeTextPlain,
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body ok, body type is FormUrlencoded",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/x-www-form-urlencoded"},
|
|
},
|
|
Body: []byte(`X-body-test1=b1&X-body-test2=b2&X-body-test2=b22`),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`X-body-test1=b1&X-body-test2=b2&X-body-test2=b22`),
|
|
ContentType: ContentTypeFormUrlencoded,
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body fail, because body not consistent, body type is FormUrlencoded",
|
|
errMsg: "expected application/x-www-form-urlencoded body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"Content-Type": {"application/x-www-form-urlencoded"},
|
|
},
|
|
Body: []byte(`X-body-test1=b1&X-body-test1=bn&X-body-test2=b2&X-body-test2=b22`),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(`X-body-test1=b1&X-body-test2=b2&X-body-test2=b22`),
|
|
ContentType: ContentTypeFormUrlencoded,
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body ok, body type is MultipartForm",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"ContentType": {"multipart/form-data; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd"},
|
|
},
|
|
Body: []byte(
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"file\"; filename=\"Screenshot.png\"\r\n" +
|
|
"Content-Type: image/png\r\n\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"name\"\r\n\r\n" +
|
|
"denzel\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"flag\"\r\n\r\n" +
|
|
"test\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd--\r\n"),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"file\"; filename=\"Screenshot.png\"\r\n" +
|
|
"Content-Type: image/png\r\n\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"name\"\r\n\r\n" +
|
|
"denzel\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"flag\"\r\n\r\n" +
|
|
"test\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd--\r\n"),
|
|
ContentType: ContentTypeMultipartForm + "; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd",
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
caseName: "compare response header&body fail, because body not consistent. body type is MultipartForm",
|
|
errMsg: "expected multipart/form-data body to be",
|
|
req: &roundtripper.Request{},
|
|
cReq: &roundtripper.CapturedRequest{},
|
|
cRes: &roundtripper.CapturedResponse{
|
|
StatusCode: 200,
|
|
Headers: map[string][]string{
|
|
"X-header-test1": {"h1"},
|
|
"X-header-test2": {"h2", "h22"},
|
|
"ContentType": {"multipart/form-data; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd"},
|
|
},
|
|
Body: []byte(
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"file\"; filename=\"Screenshot.png\"\r\n" +
|
|
"Content-Type: image/png\r\n\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"name\"\r\n\r\n" +
|
|
"higress\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"flag\"\r\n\r\n" +
|
|
"test\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd--\r\n"),
|
|
},
|
|
expected: Assertion{
|
|
Meta: AssertionMeta{TestCaseName: "", TargetBackend: "", TargetNamespace: "", CompareTarget: CompareTargetResponse},
|
|
Request: AssertionRequest{
|
|
ActualRequest: Request{},
|
|
ExpectedRequest: &ExpectedRequest{
|
|
Request: Request{},
|
|
AbsentHeaders: []string{},
|
|
},
|
|
},
|
|
Response: AssertionResponse{
|
|
ExpectedResponse: Response{
|
|
StatusCode: 200,
|
|
Headers: map[string]string{
|
|
"X-header-test1": "h1",
|
|
"X-header-test2": "h2,h22",
|
|
},
|
|
Body: []byte(
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"file\"; filename=\"Screenshot.png\"\r\n" +
|
|
"Content-Type: image/png\r\n\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"name\"\r\n\r\n" +
|
|
"denzel\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd\r\n" +
|
|
"Content-Disposition: form-data; name=\"flag\"\r\n\r\n" +
|
|
"test\r\n" +
|
|
"------WebKitFormBoundaryAnydWsQ1ajKuGoCd--\r\n"),
|
|
ContentType: ContentTypeMultipartForm + "; boundary=----WebKitFormBoundaryAnydWsQ1ajKuGoCd",
|
|
AbsentHeaders: []string{},
|
|
},
|
|
AdditionalResponseHeaders: map[string]string{},
|
|
ExpectedResponseNoRequest: false,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.caseName, func(t *testing.T) {
|
|
err := CompareResponse(c.cRes, c.expected)
|
|
if c.errMsg != "" {
|
|
require.ErrorContains(t, err, c.errMsg)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
}
|