1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package strfmt
16
17 import (
18 "strings"
19 "testing"
20 "time"
21
22 "github.com/mitchellh/mapstructure"
23 "github.com/stretchr/testify/assert"
24 "github.com/stretchr/testify/require"
25 )
26
27 type testFormat string
28
29 func (t testFormat) MarshalText() ([]byte, error) {
30 return []byte(string(t)), nil
31 }
32
33 func (t *testFormat) UnmarshalText(b []byte) error {
34 *t = testFormat(string(b))
35 return nil
36 }
37
38 func (t testFormat) String() string {
39 return string(t)
40 }
41
42 func isTestFormat(s string) bool {
43 return strings.HasPrefix(s, "tf")
44 }
45
46 type tf2 string
47
48 func (t tf2) MarshalText() ([]byte, error) {
49 return []byte(string(t)), nil
50 }
51
52 func (t *tf2) UnmarshalText(b []byte) error {
53 *t = tf2(string(b))
54 return nil
55 }
56
57 func istf2(s string) bool {
58 return strings.HasPrefix(s, "af")
59 }
60
61 func (t tf2) String() string {
62 return string(t)
63 }
64
65 type bf string
66
67 func (t bf) MarshalText() ([]byte, error) {
68 return []byte(string(t)), nil
69 }
70
71 func (t *bf) UnmarshalText(b []byte) error {
72 *t = bf(string(b))
73 return nil
74 }
75
76 func (t bf) String() string {
77 return string(t)
78 }
79
80 func isbf(s string) bool {
81 return strings.HasPrefix(s, "bf")
82 }
83
84 func istf3(s string) bool {
85 return strings.HasPrefix(s, "ff")
86 }
87
88 func init() {
89 tf := testFormat("")
90 Default.Add("test-format", &tf, isTestFormat)
91 }
92
93 func TestFormatRegistry(t *testing.T) {
94 f2 := tf2("")
95 f3 := bf("")
96 registry := NewFormats()
97
98 assert.True(t, registry.ContainsName("test-format"))
99 assert.True(t, registry.ContainsName("testformat"))
100 assert.False(t, registry.ContainsName("ttt"))
101
102 assert.True(t, registry.Validates("testformat", "tfa"))
103 assert.False(t, registry.Validates("testformat", "ffa"))
104
105 assert.True(t, registry.Add("tf2", &f2, istf2))
106 assert.True(t, registry.ContainsName("tf2"))
107 assert.False(t, registry.ContainsName("tfw"))
108 assert.True(t, registry.Validates("tf2", "afa"))
109
110 assert.False(t, registry.Add("tf2", &f3, isbf))
111 assert.True(t, registry.ContainsName("tf2"))
112 assert.False(t, registry.ContainsName("tfw"))
113 assert.True(t, registry.Validates("tf2", "bfa"))
114 assert.False(t, registry.Validates("tf2", "afa"))
115
116 assert.False(t, registry.Add("tf2", &f2, istf2))
117 assert.True(t, registry.Add("tf3", &f2, istf3))
118 assert.True(t, registry.ContainsName("tf3"))
119 assert.True(t, registry.ContainsName("tf2"))
120 assert.False(t, registry.ContainsName("tfw"))
121 assert.True(t, registry.Validates("tf3", "ffa"))
122
123 assert.True(t, registry.DelByName("tf3"))
124 assert.True(t, registry.Add("tf3", &f2, istf3))
125
126 assert.True(t, registry.DelByName("tf3"))
127 assert.False(t, registry.DelByName("unknown"))
128 assert.False(t, registry.Validates("unknown", ""))
129 }
130
131 type testStruct struct {
132 D Date `json:"d,omitempty"`
133 DT DateTime `json:"dt,omitempty"`
134 Dur Duration `json:"dur,omitempty"`
135 URI URI `json:"uri,omitempty"`
136 Eml Email `json:"eml,omitempty"`
137 UUID UUID `json:"uuid,omitempty"`
138 UUID3 UUID3 `json:"uuid3,omitempty"`
139 UUID4 UUID4 `json:"uuid4,omitempty"`
140 UUID5 UUID5 `json:"uuid5,omitempty"`
141 Hn Hostname `json:"hn,omitempty"`
142 Ipv4 IPv4 `json:"ipv4,omitempty"`
143 Ipv6 IPv6 `json:"ipv6,omitempty"`
144 Cidr CIDR `json:"cidr,omitempty"`
145 Mac MAC `json:"mac,omitempty"`
146 Isbn ISBN `json:"isbn,omitempty"`
147 Isbn10 ISBN10 `json:"isbn10,omitempty"`
148 Isbn13 ISBN13 `json:"isbn13,omitempty"`
149 Creditcard CreditCard `json:"creditcard,omitempty"`
150 Ssn SSN `json:"ssn,omitempty"`
151 Hexcolor HexColor `json:"hexcolor,omitempty"`
152 Rgbcolor RGBColor `json:"rgbcolor,omitempty"`
153 B64 Base64 `json:"b64,omitempty"`
154 Pw Password `json:"pw,omitempty"`
155 ULID ULID `json:"ulid,omitempty"`
156 }
157
158 func TestDecodeHook(t *testing.T) {
159 registry := NewFormats()
160 m := map[string]interface{}{
161 "d": "2014-12-15",
162 "dt": "2012-03-02T15:06:05.999999999Z",
163 "dur": "5s",
164 "uri": "http://www.dummy.com",
165 "eml": "dummy@dummy.com",
166 "uuid": "a8098c1a-f86e-11da-bd1a-00112444be1e",
167 "uuid3": "bcd02e22-68f0-3046-a512-327cca9def8f",
168 "uuid4": "025b0d74-00a2-4048-bf57-227c5111bb34",
169 "uuid5": "886313e1-3b8a-5372-9b90-0c9aee199e5d",
170 "hn": "somewhere.com",
171 "ipv4": "192.168.254.1",
172 "ipv6": "::1",
173 "cidr": "192.0.2.1/24",
174 "mac": "01:02:03:04:05:06",
175 "isbn": "0321751043",
176 "isbn10": "0321751043",
177 "isbn13": "978-0321751041",
178 "hexcolor": "#FFFFFF",
179 "rgbcolor": "rgb(255,255,255)",
180 "pw": "super secret stuff here",
181 "ssn": "111-11-1111",
182 "creditcard": "4111-1111-1111-1111",
183 "b64": "ZWxpemFiZXRocG9zZXk=",
184 "ulid": "7ZZZZZZZZZZZZZZZZZZZZZZZZZ",
185 }
186
187 date, _ := time.Parse(RFC3339FullDate, "2014-12-15")
188 dur, _ := ParseDuration("5s")
189 dt, _ := ParseDateTime("2012-03-02T15:06:05.999999999Z")
190 ulid, _ := ParseULID("7ZZZZZZZZZZZZZZZZZZZZZZZZZ")
191
192 exp := &testStruct{
193 D: Date(date),
194 DT: dt,
195 Dur: Duration(dur),
196 URI: URI("http://www.dummy.com"),
197 Eml: Email("dummy@dummy.com"),
198 UUID: UUID("a8098c1a-f86e-11da-bd1a-00112444be1e"),
199 UUID3: UUID3("bcd02e22-68f0-3046-a512-327cca9def8f"),
200 UUID4: UUID4("025b0d74-00a2-4048-bf57-227c5111bb34"),
201 UUID5: UUID5("886313e1-3b8a-5372-9b90-0c9aee199e5d"),
202 Hn: Hostname("somewhere.com"),
203 Ipv4: IPv4("192.168.254.1"),
204 Ipv6: IPv6("::1"),
205 Cidr: CIDR("192.0.2.1/24"),
206 Mac: MAC("01:02:03:04:05:06"),
207 Isbn: ISBN("0321751043"),
208 Isbn10: ISBN10("0321751043"),
209 Isbn13: ISBN13("978-0321751041"),
210 Creditcard: CreditCard("4111-1111-1111-1111"),
211 Ssn: SSN("111-11-1111"),
212 Hexcolor: HexColor("#FFFFFF"),
213 Rgbcolor: RGBColor("rgb(255,255,255)"),
214 B64: Base64("ZWxpemFiZXRocG9zZXk="),
215 Pw: Password("super secret stuff here"),
216 ULID: ulid,
217 }
218
219 test := new(testStruct)
220 cfg := &mapstructure.DecoderConfig{
221 DecodeHook: registry.MapStructureHookFunc(),
222
223 WeaklyTypedInput: false,
224 Result: test,
225 }
226 d, err := mapstructure.NewDecoder(cfg)
227 require.NoError(t, err)
228 err = d.Decode(m)
229 require.NoError(t, err)
230 assert.Equal(t, exp, test)
231 }
232
233 func TestDecodeDateTimeHook(t *testing.T) {
234 testCases := []struct {
235 Name string
236 Input string
237 }{
238 {
239 "empty datetime",
240 "",
241 },
242 {
243 "invalid non empty datetime",
244 "2019-01-01abc",
245 },
246 }
247 registry := NewFormats()
248 type layout struct {
249 DateTime *DateTime `json:"datetime,omitempty"`
250 }
251 for i := range testCases {
252 tc := testCases[i]
253 t.Run(tc.Name, func(t *testing.T) {
254 test := new(layout)
255 cfg := &mapstructure.DecoderConfig{
256 DecodeHook: registry.MapStructureHookFunc(),
257 WeaklyTypedInput: false,
258 Result: test,
259 }
260 d, err := mapstructure.NewDecoder(cfg)
261 require.NoError(t, err)
262 input := make(map[string]interface{})
263 input["datetime"] = tc.Input
264 err = d.Decode(input)
265 require.Error(t, err, "error expected got none")
266 })
267 }
268 }
269
270 func TestDecode_ULID_Hook_Negative(t *testing.T) {
271 t.Parallel()
272 testCases := []struct {
273 Name string
274 Input string
275 }{
276 {
277 "empty string for ulid",
278 "",
279 },
280 {
281 "invalid non empty ulid",
282 "8000000000YYYYYYYYYYYYYYYY",
283 },
284 }
285 registry := NewFormats()
286 type layout struct {
287 ULID *ULID `json:"ulid,omitempty"`
288 }
289 for i := range testCases {
290 tc := testCases[i]
291 t.Run(tc.Name, func(t *testing.T) {
292 t.Parallel()
293 test := new(layout)
294 cfg := &mapstructure.DecoderConfig{
295 DecodeHook: registry.MapStructureHookFunc(),
296 WeaklyTypedInput: false,
297 Result: test,
298 }
299 d, err := mapstructure.NewDecoder(cfg)
300 require.NoError(t, err)
301 input := make(map[string]interface{})
302 input["ulid"] = tc.Input
303 err = d.Decode(input)
304 require.Error(t, err, "error expected got none")
305 })
306 }
307 }
308
View as plain text