diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fe73ff..14f0f93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,35 @@ +# v1.15.0 (Thu May 12 2022) + +#### 🚀 Enhancement + +- New: regexp in query matching [#132](https://github.com/lamoda/gonkey/pull/132) (lev.marder@lamoda.ru) + +#### 🏠 Internal + +- Bump github.com/stretchr/testify from 1.7.0 to 1.7.1 [#156](https://github.com/lamoda/gonkey/pull/156) ([@dependabot[bot]](https://github.com/dependabot[bot])) +- #133 | fix data race [#155](https://github.com/lamoda/gonkey/pull/155) ([@architectv](https://github.com/architectv)) + +#### Authors: 3 + +- [@dependabot[bot]](https://github.com/dependabot[bot]) +- Alexey Vasyukov ([@architectv](https://github.com/architectv)) +- Lev Marder ([@ikramanop](https://github.com/ikramanop)) + +--- + +# v1.14.1 (Wed May 11 2022) + +#### 🐛 Bug Fix + +- new: add comparisonParams to BodyMatches for Json and XML [#117](https://github.com/lamoda/gonkey/pull/117) (Alexey.Tyuryumov@acronis.com [@Alexey19](https://github.com/Alexey19)) + +#### Authors: 2 + +- [@Alexey19](https://github.com/Alexey19) +- Alexey Tyuryumov (Alexey.Tyuryumov@acronis.com) + +--- + # v1.14.0 (Fri Feb 25 2022) #### 🚀 Enhancement diff --git a/README-ru.md b/README-ru.md index 031d4e1..fa0a6f3 100644 --- a/README-ru.md +++ b/README-ru.md @@ -772,6 +772,25 @@ runner.RunWithTesting(t, &runner.RunWithTestingParams{ ... ``` +###### queryMatchesRegexp + +Расширяет `queryMatches` так, чтобы можно было использовать проверку по регулярному выражению. + +Параметры: +- `expectedQuery` (обязательный) - строка параметров с которой будет сверяться запрос. Порядок параметров не имеет значения. + +Пример: +```yaml + ... + mocks: + service1: + requestConstraints: + # работает аналогично queryMatches с добавлением возможности вызова $matchRegexp + - kind: queryMatchesRegexp + expectedQuery: key1=value1&key2=$matchRegexp(\\d+)&key1=value11 + ... +``` + ###### methodIs Проверяет, что метод запроса соответствует заданному. diff --git a/README.md b/README.md index 3bda468..a0277e3 100644 --- a/README.md +++ b/README.md @@ -758,7 +758,7 @@ Checks that the GET request parameters correspond to the ones defined in the `qu Parameters: - `expectedQuery` (mandatory) - a list of parameters to compare the parameter string to. The order of parameters is not important. -Example: +Examples: ```yaml ... mocks: @@ -772,6 +772,25 @@ Example: ... ``` +###### queryMatchesRegexp + +Expands `queryMatches` so it can be used with regexp pattern matching. + +Parameters: +- `expectedQuery` (mandatory) - a list of parameters to compare the parameter string to. The order of parameters is not important. + +Example: +```yaml + ... + mocks: + service1: + requestConstraints: + # works similarly to queryMatches with an addition of $matchRegexp usage + - kind: queryMatchesRegexp + expectedQuery: key1=value1&key2=$matchRegexp(\\d+)&key1=value11 + ... +``` + ###### methodIs Checks that the request method corresponds to the expected one. @@ -783,7 +802,7 @@ There are also 2 short variations that don't require `method` parameter: - `methodIsGET` - `methodIsPOST` -Examples: +Example: ```yaml ... mocks: diff --git a/compare/compare.go b/compare/compare.go index 0d1b56a..613a019 100644 --- a/compare/compare.go +++ b/compare/compare.go @@ -9,9 +9,10 @@ import ( ) type CompareParams struct { - IgnoreValues bool - IgnoreArraysOrdering bool - DisallowExtraFields bool + IgnoreValues bool `json:"ignoreValues" yaml:"ignoreValues"` + IgnoreArraysOrdering bool `json:"ignoreArraysOrdering" yaml:"ignoreArraysOrdering"` + DisallowExtraFields bool `json:"disallowExtraFields" yaml:"disallowExtraFields"` + IgnoreDbOrdering bool `json:"IgnoreDbOrdering" yaml:"ignoreDbOrdering"` failFast bool // End compare operation after first error } diff --git a/compare/compare_query.go b/compare/compare_query.go new file mode 100644 index 0000000..1422535 --- /dev/null +++ b/compare/compare_query.go @@ -0,0 +1,57 @@ +package compare + +import ( + "fmt" + "regexp" +) + +func CompareQuery(expected, actual []string) (bool, error) { + if len(expected) != len(actual) { + return false, fmt.Errorf("expected and actual query params have different lengths") + } + + remove := func(array []string, i int) []string { + array[i] = array[len(array)-1] + return array[:len(array)-1] + } + + var expectedCopy = make([]string, len(expected)) + copy(expectedCopy, expected) + var actualCopy = make([]string, len(actual)) + copy(actualCopy, actual) + + for len(expectedCopy) != 0 { + found := false + + for i, expectedValue := range expectedCopy { + for j, actualValue := range actualCopy { + if matches := regexExprRx.FindStringSubmatch(expectedValue); matches != nil { + rx, err := regexp.Compile(matches[1]) + if err != nil { + return false, err + } + + found = rx.MatchString(actualValue) + } else { + found = expectedValue == actualValue + } + + if found { + expectedCopy = remove(expectedCopy, i) + actualCopy = remove(actualCopy, j) + break + } + } + + if found { + break + } + } + + if !found { + return false, nil + } + } + + return true, nil +} diff --git a/compare/compare_query_test.go b/compare/compare_query_test.go new file mode 100644 index 0000000..b7e8b17 --- /dev/null +++ b/compare/compare_query_test.go @@ -0,0 +1,49 @@ +package compare + +import "testing" + +func TestCompareQuery(t *testing.T) { + tests := []struct { + name string + expectedQuery []string + actualQuery []string + }{ + { + name: "simple expected and actual", + expectedQuery: []string{"cake"}, + actualQuery: []string{"cake"}, + }, + { + name: "expected and actual with two values", + expectedQuery: []string{"cake", "tea"}, + actualQuery: []string{"cake", "tea"}, + }, + { + name: "expected and actual with two values and different order", + expectedQuery: []string{"cake", "tea"}, + actualQuery: []string{"tea", "cake"}, + }, + { + name: "expected and actual with same values", + expectedQuery: []string{"tea", "cake", "tea"}, + actualQuery: []string{"cake", "tea", "tea"}, + }, + { + name: "expected and actual with regexp", + expectedQuery: []string{"tea", "$matchRegexp(^c\\w+)"}, + actualQuery: []string{"cake", "tea"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ok, err := CompareQuery(tt.expectedQuery, tt.actualQuery) + if err != nil { + t.Error(err) + } + if !ok { + t.Errorf("expected and actual queries do not match") + } + }) + } +} diff --git a/go.mod b/go.mod index b90a8e9..0498714 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/kylelemons/godebug v1.1.0 github.com/lib/pq v1.3.0 github.com/mattn/go-colorable v0.1.12 // indirect - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 github.com/tidwall/gjson v1.13.0 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 diff --git a/go.sum b/go.sum index 611bc77..a2c51b4 100644 --- a/go.sum +++ b/go.sum @@ -18,18 +18,12 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc= -github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M= github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= -github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= diff --git a/mocks/loader.go b/mocks/loader.go index 7d9aac1..26c3749 100644 --- a/mocks/loader.go +++ b/mocks/loader.go @@ -5,6 +5,8 @@ import ( "fmt" "net/http" "strconv" + + "github.com/lamoda/gonkey/compare" ) type Loader struct { @@ -292,14 +294,17 @@ func (l *Loader) loadConstraintOfKind(kind string, def map[interface{}]interface case "nop": return &nopConstraint{}, nil case "bodyMatchesJSON": - *ak = append(*ak, "body") + *ak = append(*ak, "body", "comparisonParams") return l.loadBodyMatchesJSONConstraint(def) case "bodyJSONFieldMatchesJSON": - *ak = append(*ak, "path", "value") + *ak = append(*ak, "path", "value", "comparisonParams") return l.loadBodyJSONFieldMatchesJSONConstraint(def) case "queryMatches": *ak = append(*ak, "expectedQuery") return l.loadQueryMatchesConstraint(def) + case "queryMatchesRegexp": + *ak = append(*ak, "expectedQuery") + return l.loadQueryMatchesRegexpConstraint(def) case "methodIsGET": return &methodConstraint{method: "GET"}, nil case "methodIsPOST": @@ -317,13 +322,53 @@ func (l *Loader) loadConstraintOfKind(kind string, def map[interface{}]interface *ak = append(*ak, "path", "regexp") return l.loadPathMatchesConstraint(def) case "bodyMatchesXML": - *ak = append(*ak, "body") + *ak = append(*ak, "body", "comparisonParams") return l.loadBodyMatchesXMLConstraint(def) default: return nil, fmt.Errorf("unknown constraint: %s", kind) } } +func readCompareParams(def map[interface{}]interface{}) (compare.CompareParams, error) { + params := compare.CompareParams{ + IgnoreArraysOrdering: true, + } + + p, ok := def["comparisonParams"] + if !ok { + return params, nil + } + + values, ok := p.(map[interface{}]interface{}) + if !ok { + return params, errors.New("`comparisonParams` can't be parsed") + } + + mapping := map[string]*bool{ + "ignoreValues": ¶ms.IgnoreValues, + "ignoreArraysOrdering": ¶ms.IgnoreArraysOrdering, + "disallowExtraFields": ¶ms.DisallowExtraFields, + } + + for key, val := range values { + skey, ok := key.(string) + if !ok { + return params, errors.New("`comparisonParams` has non-string key") + } + + bval, ok := val.(bool) + if !ok { + return params, errors.New("`comparisonParams` has non-bool values") + } + + if pbval, ok := mapping[skey]; ok { + *pbval = bval + } + + } + return params, nil +} + func (l *Loader) loadBodyMatchesJSONConstraint(def map[interface{}]interface{}) (verifier, error) { c, ok := def["body"] if !ok { @@ -333,7 +378,13 @@ func (l *Loader) loadBodyMatchesJSONConstraint(def map[interface{}]interface{}) if !ok { return nil, errors.New("`body` must be string") } - return newBodyMatchesJSONConstraint(body) + + params, err := readCompareParams(def) + if err != nil { + return nil, err + } + + return newBodyMatchesJSONConstraint(body, params) } func (l *Loader) loadBodyJSONFieldMatchesJSONConstraint(def map[interface{}]interface{}) (verifier, error) { @@ -354,7 +405,13 @@ func (l *Loader) loadBodyJSONFieldMatchesJSONConstraint(def map[interface{}]inte if !ok { return nil, errors.New("`value` must be string") } - return newBodyJSONFieldMatchesJSONConstraint(path, value) + + params, err := readCompareParams(def) + if err != nil { + return nil, err + } + + return newBodyJSONFieldMatchesJSONConstraint(path, value, params) } func (l *Loader) loadBodyMatchesXMLConstraint(def map[interface{}]interface{}) (verifier, error) { @@ -366,7 +423,13 @@ func (l *Loader) loadBodyMatchesXMLConstraint(def map[interface{}]interface{}) ( if !ok { return nil, errors.New("`body` must be string") } - return newBodyMatchesXMLConstraint(body) + + params, err := readCompareParams(def) + if err != nil { + return nil, err + } + + return newBodyMatchesXMLConstraint(body, params) } func (l *Loader) loadPathMatchesConstraint(def map[interface{}]interface{}) (verifier, error) { @@ -398,6 +461,18 @@ func (l *Loader) loadQueryMatchesConstraint(def map[interface{}]interface{}) (ve return newQueryConstraint(query) } +func (l *Loader) loadQueryMatchesRegexpConstraint(def map[interface{}]interface{}) (verifier, error) { + c, ok := def["expectedQuery"] + if !ok { + return nil, errors.New("`queryMatchesRegexp` requires `expectedQuery` key") + } + query, ok := c.(string) + if !ok { + return nil, errors.New("`expectedQuery` must be string") + } + return newQueryRegexpConstraint(query) +} + func (l *Loader) loadMethodIsConstraint(def map[interface{}]interface{}) (verifier, error) { c, ok := def["method"] if !ok { diff --git a/mocks/request_constraint.go b/mocks/request_constraint.go index e22cc16..37d10ba 100644 --- a/mocks/request_constraint.go +++ b/mocks/request_constraint.go @@ -32,9 +32,10 @@ func (c *nopConstraint) Verify(r *http.Request) []error { type bodyMatchesXMLConstraint struct { expectedBody interface{} + compareParams compare.CompareParams } -func newBodyMatchesXMLConstraint(expected string) (verifier, error) { +func newBodyMatchesXMLConstraint(expected string, params compare.CompareParams) (verifier, error) { expectedBody, err := xmlparsing.Parse(expected) if err != nil { return nil, err @@ -42,6 +43,7 @@ func newBodyMatchesXMLConstraint(expected string) (verifier, error) { res := &bodyMatchesXMLConstraint{ expectedBody: expectedBody, + compareParams: params, } return res, nil } @@ -62,19 +64,17 @@ func (c *bodyMatchesXMLConstraint) Verify(r *http.Request) []error { return []error{err} } - params := compare.CompareParams{ - IgnoreArraysOrdering: true, - } - return compare.Compare(c.expectedBody, actual, params) + return compare.Compare(c.expectedBody, actual, c.compareParams) } type bodyMatchesJSONConstraint struct { verifier expectedBody interface{} + compareParams compare.CompareParams } -func newBodyMatchesJSONConstraint(expected string) (verifier, error) { +func newBodyMatchesJSONConstraint(expected string, params compare.CompareParams) (verifier, error) { var expectedBody interface{} err := json.Unmarshal([]byte(expected), &expectedBody) if err != nil { @@ -82,6 +82,7 @@ func newBodyMatchesJSONConstraint(expected string) (verifier, error) { } res := &bodyMatchesJSONConstraint{ expectedBody: expectedBody, + compareParams: params, } return res, nil } @@ -101,18 +102,16 @@ func (c *bodyMatchesJSONConstraint) Verify(r *http.Request) []error { if err != nil { return []error{err} } - params := compare.CompareParams{ - IgnoreArraysOrdering: true, - } - return compare.Compare(c.expectedBody, actual, params) + return compare.Compare(c.expectedBody, actual, c.compareParams) } type bodyJSONFieldMatchesJSONConstraint struct { path string expected interface{} + compareParams compare.CompareParams } -func newBodyJSONFieldMatchesJSONConstraint(path, expected string) (verifier, error) { +func newBodyJSONFieldMatchesJSONConstraint(path, expected string, params compare.CompareParams) (verifier, error) { var v interface{} err := json.Unmarshal([]byte(expected), &v) if err != nil { @@ -121,6 +120,7 @@ func newBodyJSONFieldMatchesJSONConstraint(path, expected string) (verifier, err res := &bodyJSONFieldMatchesJSONConstraint{ path: path, expected: v, + compareParams: params, } return res, nil } @@ -147,10 +147,7 @@ func (c *bodyJSONFieldMatchesJSONConstraint) Verify(r *http.Request) []error { if err != nil { return []error{err} } - params := compare.CompareParams{ - IgnoreArraysOrdering: true, - } - return compare.Compare(c.expected, actual, params) + return compare.Compare(c.expected, actual, c.compareParams) } type methodConstraint struct { @@ -243,6 +240,58 @@ func (c *queryConstraint) Verify(r *http.Request) (errors []error) { return errors } +type queryRegexpConstraint struct { + expectedQuery map[string][]string +} + +func newQueryRegexpConstraint(query string) (*queryRegexpConstraint, error) { + // user may begin his query with '?', just omit it in this case + if strings.HasPrefix(query, "?") { + query = query[1:] + } + + rawParams := strings.Split(query, "&") + + expectedQuery := map[string][]string{} + for _, rawParam := range rawParams { + parts := strings.Split(rawParam, "=") + if len(parts) != 2 { + return nil, fmt.Errorf("error parsing query: got %d parts, expected 2", len(parts)) + } + + _, ok := expectedQuery[parts[0]] + if !ok { + expectedQuery[parts[0]] = make([]string, 0) + } + expectedQuery[parts[0]] = append(expectedQuery[parts[0]], parts[1]) + } + + return &queryRegexpConstraint{expectedQuery}, nil +} + +func (c *queryRegexpConstraint) Verify(r *http.Request) (errors []error) { + gotQuery := r.URL.Query() + for key, want := range c.expectedQuery { + got, ok := gotQuery[key] + if !ok { + errors = append(errors, fmt.Errorf("'%s' parameter is missing in expQuery", key)) + continue + } + + if ok, err := compare.CompareQuery(want, got); err != nil { + errors = append(errors, fmt.Errorf( + "'%s' parameters comparison failed. \n %s'", key, err.Error(), + )) + } else if !ok { + errors = append(errors, fmt.Errorf( + "'%s' parameters are not equal.\n Got: %s \n Want: %s", key, got, want, + )) + } + } + + return errors +} + type pathConstraint struct { verifier diff --git a/mocks/request_constraint_test.go b/mocks/request_constraint_test.go index fca79cf..b330eb7 100644 --- a/mocks/request_constraint_test.go +++ b/mocks/request_constraint_test.go @@ -98,6 +98,114 @@ func Test_queryConstraint_Verify(t *testing.T) { } } +func Test_newQueryRegexpConstraint(t *testing.T) { + tests := []struct { + name string + query string + want queryRegexpConstraint + }{ + { + name: "simple expQuery", + query: "a=1&b=2&a=3", + want: queryRegexpConstraint{expectedQuery: map[string][]string{"a": {"1", "3"}, "b": {"2"}}}, + }, + { + name: "expQuery written with '?'", + query: "?a=1&b=2&a=3", + want: queryRegexpConstraint{expectedQuery: map[string][]string{"a": {"1", "3"}, "b": {"2"}}}, + }, + { + name: "expQuery contains multiple '?'", + query: "?a=1&b=?&a=3", + want: queryRegexpConstraint{expectedQuery: map[string][]string{"a": {"1", "3"}, "b": {"?"}}}, + }, + { + name: "expQuery contains 'matchRegexp'", + query: "a=1&b=$matchRegexp(\\d+)&a=3", + want: queryRegexpConstraint{expectedQuery: map[string][]string{"a": {"1", "3"}, "b": {"$matchRegexp(\\d+)"}}}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := newQueryRegexpConstraint(tt.query) + if err != nil { + t.Errorf("newQueryRegexpConstraint() error = %v", err) + return + } + if got == nil { + t.Fatalf("unexpected. got nil instead of queryRegexpConstraint") + } + if !reflect.DeepEqual(*got, tt.want) { + t.Errorf("newQueryRegexpConstraint() = %v, want %v", *got, tt.want) + } + }) + } +} + +func Test_queryRegexpConstraint_Verify(t *testing.T) { + tests := []struct { + name string + expQuery url.Values + req *http.Request + wantErrors int + }{ + { + name: "expected", + expQuery: map[string][]string{"food": {"cake", "tea"}, "people": {"2"}}, + req: newTestRequest("food=cake&food=tea&people=2"), + wantErrors: 0, + }, + { + name: "expected but different order", + expQuery: map[string][]string{"food": {"cake", "tea"}, "people": {"2"}}, + req: newTestRequest("food=tea&food=cake&people=2"), + wantErrors: 0, + }, + { + name: "unexpected value", + expQuery: map[string][]string{"food": {"cake", "tea"}, "people": {"2"}}, + req: newTestRequest("food=cake&food=beer&people=3"), + wantErrors: 2, + }, + { + name: "key is missing", + expQuery: map[string][]string{"food": {"cake", "tea"}, "people": {"2"}}, + req: newTestRequest("food=cake&food=tea"), + wantErrors: 1, + }, + { + name: "unexpected keys are ignored is missing", + expQuery: map[string][]string{"food": {"cake", "tea"}, "people": {"2"}}, + req: newTestRequest("food=cake&food=tea&people=2&one-more=person"), + wantErrors: 0, + }, + { + name: "regexp in expected query", + expQuery: map[string][]string{"food": {"cake", "$matchRegexp(\\w+)"}, "people": {"$matchRegexp(\\d+)"}}, + req: newTestRequest("food=cake&food=tea&people=2675"), + wantErrors: 0, + }, + { + name: "expected and actual parameters have different lengths", + expQuery: map[string][]string{"food": {"cake", "tea"}, "people": {"2"}}, + req: newTestRequest("food=cake&food=tea&food=coffee&people=2"), + wantErrors: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &queryRegexpConstraint{ + expectedQuery: tt.expQuery, + } + if gotErrors := c.Verify(tt.req); len(gotErrors) != tt.wantErrors { + t.Errorf("unexpected amount of errors. Got %v, want %v. Errors are: '%v'", + len(gotErrors), tt.wantErrors, gotErrors, + ) + } + }) + } +} + func newTestRequest(query string) *http.Request { r, _ := http.NewRequest("GET", "http://localhost/?"+query, nil) return r diff --git a/mocks/service_mock.go b/mocks/service_mock.go index 5032abf..c0b32eb 100644 --- a/mocks/service_mock.go +++ b/mocks/service_mock.go @@ -12,7 +12,7 @@ type ServiceMock struct { listener net.Listener mock *definition defaultDefinition *definition - sync.Mutex + sync.RWMutex errors []error ServiceName string @@ -85,6 +85,9 @@ func (m *ServiceMock) ResetRunningContext() { } func (m *ServiceMock) EndRunningContext() []error { + m.RLock() + defer m.RUnlock() + errs := append(m.errors, m.mock.EndRunningContext()...) for i, e := range errs { errs[i] = &Error{ diff --git a/testloader/yaml_file/test_definition.go b/testloader/yaml_file/test_definition.go index 01648f0..0b010a5 100644 --- a/testloader/yaml_file/test_definition.go +++ b/testloader/yaml_file/test_definition.go @@ -1,6 +1,9 @@ package yaml_file -import "github.com/lamoda/gonkey/models" +import ( + "github.com/lamoda/gonkey/compare" + "github.com/lamoda/gonkey/models" +) type TestDefinition struct { Name string `json:"name" yaml:"name"` @@ -19,7 +22,7 @@ type TestDefinition struct { HeadersVal map[string]string `json:"headers" yaml:"headers"` CookiesVal map[string]string `json:"cookies" yaml:"cookies"` Cases []CaseData `json:"cases" yaml:"cases"` - ComparisonParams comparisonParams `json:"comparisonParams" yaml:"comparisonParams"` + ComparisonParams compare.CompareParams `json:"comparisonParams" yaml:"comparisonParams"` FixtureFiles []string `json:"fixtures" yaml:"fixtures"` MocksDefinition map[string]interface{} `json:"mocks" yaml:"mocks"` PauseValue int `json:"pause" yaml:"pause"` @@ -37,13 +40,6 @@ type CaseData struct { DbResponse []string `json:"dbResponse" yaml:"dbResponse"` } -type comparisonParams struct { - IgnoreValues bool `json:"ignoreValues" yaml:"ignoreValues"` - IgnoreArraysOrdering bool `json:"ignoreArraysOrdering" yaml:"ignoreArraysOrdering"` - DisallowExtraFields bool `json:"disallowExtraFields" yaml:"disallowExtraFields"` - IgnoreDbOrdering bool `json:"IgnoreDbOrdering" yaml:"ignoreDbOrdering"` -} - type scriptParams struct { PathTmpl string `json:"path" yaml:"path"` Timeout int `json:"timeout" yaml:"timeout"`