-
Notifications
You must be signed in to change notification settings - Fork 19
/
string_value_matcher.go
187 lines (156 loc) · 6.01 KB
/
string_value_matcher.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package wiremock
import (
"encoding/json"
"fmt"
"regexp"
)
type MatcherInterface interface {
json.Marshaler
ParseMatcher() map[string]interface{}
}
type BasicParamMatcher interface {
json.Marshaler
ParseMatcher() map[string]interface{}
Or(stringMatcher BasicParamMatcher) BasicParamMatcher
And(stringMatcher BasicParamMatcher) BasicParamMatcher
}
type StringValueMatcher struct {
strategy ParamMatchingStrategy
value string
flags []string
}
// MarshalJSON returns the JSON encoding of the matcher.
func (m StringValueMatcher) MarshalJSON() ([]byte, error) {
return json.Marshal(m.ParseMatcher())
}
// ParseMatcher returns the map representation of the structure.
func (m StringValueMatcher) ParseMatcher() map[string]interface{} {
jsonMap := make(map[string]interface{}, 1+len(m.flags))
if m.strategy != "" {
jsonMap[string(m.strategy)] = m.value
}
for _, flag := range m.flags {
jsonMap[flag] = true
}
return jsonMap
}
// Or returns a logical OR of the two matchers.
func (m StringValueMatcher) Or(matcher BasicParamMatcher) BasicParamMatcher {
return Or(m, matcher)
}
// And returns a logical AND of the two matchers.
func (m StringValueMatcher) And(matcher BasicParamMatcher) BasicParamMatcher {
return And(m, matcher)
}
// addPrefixToMatcher adds prefix to matcher.
// In case of "contains", "absent", "doesNotContain" prefix is not added as it doesn't affect the match result
func (m StringValueMatcher) addPrefixToMatcher(prefix string) BasicParamMatcher {
switch m.strategy {
case ParamEqualTo, ParamEqualToJson, ParamEqualToXml, ParamMatchesJsonPath, ParamMatchesXPath:
m.value = prefix + m.value
case ParamMatches, ParamDoesNotMatch:
if regexContainsStartAnchor(m.value) {
m.value = m.value[1:]
}
m.value = fmt.Sprintf("^%s", prefix) + m.value
}
return m
}
// NewStringValueMatcher creates a new StringValueMatcher.
func NewStringValueMatcher(strategy ParamMatchingStrategy, value string, flags ...string) StringValueMatcher {
return StringValueMatcher{
strategy: strategy,
value: value,
flags: flags,
}
}
// EqualTo returns a matcher that matches when the parameter equals the specified value.
func EqualTo(value string) BasicParamMatcher {
return NewStringValueMatcher(ParamEqualTo, value)
}
// EqualToIgnoreCase returns a matcher that matches when the parameter equals the specified value, ignoring case.
func EqualToIgnoreCase(value string) BasicParamMatcher {
return NewStringValueMatcher(ParamEqualTo, value, "caseInsensitive")
}
// Matching returns a matcher that matches when the parameter matches the specified regular expression.
func Matching(param string) BasicParamMatcher {
return NewStringValueMatcher(ParamMatches, param)
}
// EqualToXml returns a matcher that matches when the parameter is equal to the specified XML.
func EqualToXml(param string) BasicParamMatcher {
return NewStringValueMatcher(ParamEqualToXml, param)
}
// EqualToJson returns a matcher that matches when the parameter is equal to the specified JSON.
func EqualToJson(param string, equalJsonFlags ...EqualFlag) BasicParamMatcher {
flags := make([]string, len(equalJsonFlags))
for i, flag := range equalJsonFlags {
flags[i] = string(flag)
}
return NewStringValueMatcher(ParamEqualToJson, param, flags...)
}
// MustEqualToJson returns a matcher that matches when the parameter is equal to the specified JSON.
// This method panics if param cannot be marshaled to JSON.
func MustEqualToJson(param any, equalJsonFlags ...EqualFlag) BasicParamMatcher {
if str, ok := param.(string); ok {
return EqualToJson(str, equalJsonFlags...)
}
if jsonParam, err := json.Marshal(param); err != nil {
panic(fmt.Sprintf("Unable to marshal parameter to JSON: %v", err))
} else {
return EqualToJson(string(jsonParam), equalJsonFlags...)
}
}
// MatchingXPath returns a matcher that matches when the parameter matches the specified XPath.
func MatchingXPath(param string) BasicParamMatcher {
return NewStringValueMatcher(ParamMatchesXPath, param)
}
// MatchingJsonPath returns a matcher that matches when the parameter matches the specified JSON path.
func MatchingJsonPath(param string) BasicParamMatcher {
return NewStringValueMatcher(ParamMatchesJsonPath, param)
}
// NotMatching returns a matcher that matches when the parameter does not match the specified regular expression.
func NotMatching(param string) BasicParamMatcher {
return NewStringValueMatcher(ParamDoesNotMatch, param)
}
// Absent returns a matcher that matches when the parameter is absent.
func Absent() BasicParamMatcher {
return StringValueMatcher{
flags: []string{string(ParamAbsent)},
}
}
// Contains returns a matcher that matches when the parameter contains the specified value.
func Contains(param string) BasicParamMatcher {
return NewStringValueMatcher(ParamContains, param)
}
// NotContains returns a matcher that matches when the parameter does not contain the specified value.
func NotContains(param string) BasicParamMatcher {
return NewStringValueMatcher(ParamDoesNotContains, param)
}
// StartsWith returns a matcher that matches when the parameter starts with the specified prefix.
// Matches also when prefix alone is the whole expression
func StartsWith(prefix string) BasicParamMatcher {
regex := fmt.Sprintf(`^%s\s*\S*`, regexp.QuoteMeta(prefix))
return NewStringValueMatcher(ParamMatches, regex)
}
type JSONSchemaMatcher struct {
StringValueMatcher
schemaVersion string
}
// MatchesJsonSchema returns a matcher that matches when the parameter matches the specified JSON schema.
// Required wiremock version >= 3.0.0
func MatchesJsonSchema(schema string, schemaVersion string) BasicParamMatcher {
return JSONSchemaMatcher{
StringValueMatcher: NewStringValueMatcher(ParamMatchesJsonSchema, schema),
schemaVersion: schemaVersion,
}
}
// MarshalJSON returns the JSON encoding of the matcher.
func (m JSONSchemaMatcher) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]string{
string(m.strategy): m.value,
"schemaVersion": m.schemaVersion,
})
}
func regexContainsStartAnchor(regex string) bool {
return len(regex) > 0 && regex[0] == '^'
}