1package govalidator
2
3import (
4	"fmt"
5	"strings"
6	"testing"
7	"time"
8)
9
10func init() {
11	CustomTypeTagMap.Set("customFalseValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool {
12		return false
13	}))
14	CustomTypeTagMap.Set("customTrueValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool {
15		return true
16	}))
17}
18
19func TestIsAlpha(t *testing.T) {
20	t.Parallel()
21
22	var tests = []struct {
23		param    string
24		expected bool
25	}{
26		{"\n", false},
27		{"\r", false},
28		{"Ⅸ", false},
29		{"", true},
30		{"   fooo   ", false},
31		{"abc!!!", false},
32		{"abc1", false},
33		{"abc〩", false},
34		{"abc", true},
35		{"소주", false},
36		{"ABC", true},
37		{"FoObAr", true},
38		{"소aBC", false},
39		{"소", false},
40		{"달기&Co.", false},
41		{"〩Hours", false},
42		{"\ufff0", false},
43		{"\u0070", true},  //UTF-8(ASCII): p
44		{"\u0026", false}, //UTF-8(ASCII): &
45		{"\u0030", false}, //UTF-8(ASCII): 0
46		{"123", false},
47		{"0123", false},
48		{"-00123", false},
49		{"0", false},
50		{"-0", false},
51		{"123.123", false},
52		{" ", false},
53		{".", false},
54		{"-1¾", false},
55		{"1¾", false},
56		{"〥〩", false},
57		{"모자", false},
58		{"ix", true},
59		{"۳۵۶۰", false},
60		{"1--", false},
61		{"1-1", false},
62		{"-", false},
63		{"--", false},
64		{"1++", false},
65		{"1+1", false},
66		{"+", false},
67		{"++", false},
68		{"+1", false},
69	}
70	for _, test := range tests {
71		actual := IsAlpha(test.param)
72		if actual != test.expected {
73			t.Errorf("Expected IsAlpha(%q) to be %v, got %v", test.param, test.expected, actual)
74		}
75	}
76}
77
78func TestIsUTFLetter(t *testing.T) {
79	t.Parallel()
80
81	var tests = []struct {
82		param    string
83		expected bool
84	}{
85		{"\n", false},
86		{"\r", false},
87		{"Ⅸ", false},
88		{"", true},
89		{"   fooo   ", false},
90		{"abc!!!", false},
91		{"abc1", false},
92		{"abc〩", false},
93		{"", true},
94		{"abc", true},
95		{"소주", true},
96		{"ABC", true},
97		{"FoObAr", true},
98		{"소aBC", true},
99		{"소", true},
100		{"달기&Co.", false},
101		{"〩Hours", false},
102		{"\ufff0", false},
103		{"\u0070", true},  //UTF-8(ASCII): p
104		{"\u0026", false}, //UTF-8(ASCII): &
105		{"\u0030", false}, //UTF-8(ASCII): 0
106		{"123", false},
107		{"0123", false},
108		{"-00123", false},
109		{"0", false},
110		{"-0", false},
111		{"123.123", false},
112		{" ", false},
113		{".", false},
114		{"-1¾", false},
115		{"1¾", false},
116		{"〥〩", false},
117		{"모자", true},
118		{"ix", true},
119		{"۳۵۶۰", false},
120		{"1--", false},
121		{"1-1", false},
122		{"-", false},
123		{"--", false},
124		{"1++", false},
125		{"1+1", false},
126		{"+", false},
127		{"++", false},
128		{"+1", false},
129	}
130	for _, test := range tests {
131		actual := IsUTFLetter(test.param)
132		if actual != test.expected {
133			t.Errorf("Expected IsUTFLetter(%q) to be %v, got %v", test.param, test.expected, actual)
134		}
135	}
136}
137
138func TestIsAlphanumeric(t *testing.T) {
139	t.Parallel()
140
141	var tests = []struct {
142		param    string
143		expected bool
144	}{
145		{"\n", false},
146		{"\r", false},
147		{"Ⅸ", false},
148		{"", true},
149		{"   fooo   ", false},
150		{"abc!!!", false},
151		{"abc123", true},
152		{"ABC111", true},
153		{"abc1", true},
154		{"abc〩", false},
155		{"abc", true},
156		{"소주", false},
157		{"ABC", true},
158		{"FoObAr", true},
159		{"소aBC", false},
160		{"소", false},
161		{"달기&Co.", false},
162		{"〩Hours", false},
163		{"\ufff0", false},
164		{"\u0070", true},  //UTF-8(ASCII): p
165		{"\u0026", false}, //UTF-8(ASCII): &
166		{"\u0030", true},  //UTF-8(ASCII): 0
167		{"123", true},
168		{"0123", true},
169		{"-00123", false},
170		{"0", true},
171		{"-0", false},
172		{"123.123", false},
173		{" ", false},
174		{".", false},
175		{"-1¾", false},
176		{"1¾", false},
177		{"〥〩", false},
178		{"모자", false},
179		{"ix", true},
180		{"۳۵۶۰", false},
181		{"1--", false},
182		{"1-1", false},
183		{"-", false},
184		{"--", false},
185		{"1++", false},
186		{"1+1", false},
187		{"+", false},
188		{"++", false},
189		{"+1", false},
190	}
191	for _, test := range tests {
192		actual := IsAlphanumeric(test.param)
193		if actual != test.expected {
194			t.Errorf("Expected IsAlphanumeric(%q) to be %v, got %v", test.param, test.expected, actual)
195		}
196	}
197}
198
199func TestIsUTFLetterNumeric(t *testing.T) {
200	t.Parallel()
201
202	var tests = []struct {
203		param    string
204		expected bool
205	}{
206		{"\n", false},
207		{"\r", false},
208		{"Ⅸ", true},
209		{"", true},
210		{"   fooo   ", false},
211		{"abc!!!", false},
212		{"abc1", true},
213		{"abc〩", true},
214		{"abc", true},
215		{"소주", true},
216		{"ABC", true},
217		{"FoObAr", true},
218		{"소aBC", true},
219		{"소", true},
220		{"달기&Co.", false},
221		{"〩Hours", true},
222		{"\ufff0", false},
223		{"\u0070", true},  //UTF-8(ASCII): p
224		{"\u0026", false}, //UTF-8(ASCII): &
225		{"\u0030", true},  //UTF-8(ASCII): 0
226		{"123", true},
227		{"0123", true},
228		{"-00123", false},
229		{"0", true},
230		{"-0", false},
231		{"123.123", false},
232		{" ", false},
233		{".", false},
234		{"-1¾", false},
235		{"1¾", true},
236		{"〥〩", true},
237		{"모자", true},
238		{"ix", true},
239		{"۳۵۶۰", true},
240		{"1--", false},
241		{"1-1", false},
242		{"-", false},
243		{"--", false},
244		{"1++", false},
245		{"1+1", false},
246		{"+", false},
247		{"++", false},
248		{"+1", false},
249	}
250	for _, test := range tests {
251		actual := IsUTFLetterNumeric(test.param)
252		if actual != test.expected {
253			t.Errorf("Expected IsUTFLetterNumeric(%q) to be %v, got %v", test.param, test.expected, actual)
254		}
255	}
256}
257
258func TestIsNumeric(t *testing.T) {
259	t.Parallel()
260
261	var tests = []struct {
262		param    string
263		expected bool
264	}{
265		{"\n", false},
266		{"\r", false},
267		{"Ⅸ", false},
268		{"", true},
269		{"   fooo   ", false},
270		{"abc!!!", false},
271		{"abc1", false},
272		{"abc〩", false},
273		{"abc", false},
274		{"소주", false},
275		{"ABC", false},
276		{"FoObAr", false},
277		{"소aBC", false},
278		{"소", false},
279		{"달기&Co.", false},
280		{"〩Hours", false},
281		{"\ufff0", false},
282		{"\u0070", false}, //UTF-8(ASCII): p
283		{"\u0026", false}, //UTF-8(ASCII): &
284		{"\u0030", true},  //UTF-8(ASCII): 0
285		{"123", true},
286		{"0123", true},
287		{"-00123", false},
288		{"+00123", false},
289		{"0", true},
290		{"-0", false},
291		{"123.123", false},
292		{" ", false},
293		{".", false},
294		{"12��3", false},
295		{"-1¾", false},
296		{"1¾", false},
297		{"〥〩", false},
298		{"모자", false},
299		{"ix", false},
300		{"۳۵۶۰", false},
301		{"1--", false},
302		{"1-1", false},
303		{"-", false},
304		{"--", false},
305		{"1++", false},
306		{"1+1", false},
307		{"+", false},
308		{"++", false},
309		{"+1", false},
310	}
311	for _, test := range tests {
312		actual := IsNumeric(test.param)
313		if actual != test.expected {
314			t.Errorf("Expected IsNumeric(%q) to be %v, got %v", test.param, test.expected, actual)
315		}
316	}
317}
318
319func TestIsUTFNumeric(t *testing.T) {
320	t.Parallel()
321
322	var tests = []struct {
323		param    string
324		expected bool
325	}{
326		{"\n", false},
327		{"\r", false},
328		{"Ⅸ", true},
329		{"", true},
330		{"   fooo   ", false},
331		{"abc!!!", false},
332		{"abc1", false},
333		{"abc〩", false},
334		{"abc", false},
335		{"소주", false},
336		{"ABC", false},
337		{"FoObAr", false},
338		{"소aBC", false},
339		{"소", false},
340		{"달기&Co.", false},
341		{"〩Hours", false},
342		{"\ufff0", false},
343		{"\u0070", false}, //UTF-8(ASCII): p
344		{"\u0026", false}, //UTF-8(ASCII): &
345		{"\u0030", true},  //UTF-8(ASCII): 0
346		{"123", true},
347		{"0123", true},
348		{"-00123", true},
349		{"0", true},
350		{"-0", true},
351		{"--0", false},
352		{"-0-", false},
353		{"123.123", false},
354		{" ", false},
355		{".", false},
356		{"12��3", true},
357		{"-1¾", true},
358		{"1¾", true},
359		{"〥〩", true},
360		{"모자", false},
361		{"ix", false},
362		{"۳۵۶۰", true},
363		{"1++", false},
364		{"1+1", false},
365		{"+", false},
366		{"++", false},
367		{"+1", true},
368	}
369	for _, test := range tests {
370		actual := IsUTFNumeric(test.param)
371		if actual != test.expected {
372			t.Errorf("Expected IsUTFNumeric(%q) to be %v, got %v", test.param, test.expected, actual)
373		}
374	}
375}
376
377func TestIsUTFDigit(t *testing.T) {
378	t.Parallel()
379
380	var tests = []struct {
381		param    string
382		expected bool
383	}{
384
385		{"\n", false},
386		{"\r", false},
387		{"Ⅸ", false},
388		{"", true},
389		{"   fooo   ", false},
390		{"abc!!!", false},
391		{"abc1", false},
392		{"abc〩", false},
393		{"abc", false},
394		{"소주", false},
395		{"ABC", false},
396		{"FoObAr", false},
397		{"소aBC", false},
398		{"소", false},
399		{"달기&Co.", false},
400		{"〩Hours", false},
401		{"\ufff0", false},
402		{"\u0070", false}, //UTF-8(ASCII): p
403		{"\u0026", false}, //UTF-8(ASCII): &
404		{"\u0030", true},  //UTF-8(ASCII): 0
405		{"123", true},
406		{"0123", true},
407		{"-00123", true},
408		{"0", true},
409		{"-0", true},
410		{"--0", false},
411		{"-0-", false},
412		{"123.123", false},
413		{" ", false},
414		{".", false},
415		{"12��3", false},
416		{"1483920", true},
417		{"", true},
418		{"۳۵۶۰", true},
419		{"-29", true},
420		{"-1¾", false},
421		{"1¾", false},
422		{"〥〩", false},
423		{"모자", false},
424		{"ix", false},
425		{"۳۵۶۰", true},
426		{"1++", false},
427		{"1+1", false},
428		{"+", false},
429		{"++", false},
430		{"+1", true},
431	}
432	for _, test := range tests {
433		actual := IsUTFDigit(test.param)
434		if actual != test.expected {
435			t.Errorf("Expected IsUTFDigit(%q) to be %v, got %v", test.param, test.expected, actual)
436		}
437	}
438}
439
440func TestIsLowerCase(t *testing.T) {
441	t.Parallel()
442
443	var tests = []struct {
444		param    string
445		expected bool
446	}{
447		{"", true},
448		{"abc123", true},
449		{"abc", true},
450		{"a b c", true},
451		{"abcß", true},
452		{"abcẞ", false},
453		{"ABCẞ", false},
454		{"tr竪s 端ber", true},
455		{"fooBar", false},
456		{"123ABC", false},
457		{"ABC123", false},
458		{"ABC", false},
459		{"S T R", false},
460		{"fooBar", false},
461		{"abacaba123", true},
462	}
463	for _, test := range tests {
464		actual := IsLowerCase(test.param)
465		if actual != test.expected {
466			t.Errorf("Expected IsLowerCase(%q) to be %v, got %v", test.param, test.expected, actual)
467		}
468	}
469}
470
471func TestIsUpperCase(t *testing.T) {
472	t.Parallel()
473
474	var tests = []struct {
475		param    string
476		expected bool
477	}{
478		{"", true},
479		{"abc123", false},
480		{"abc", false},
481		{"a b c", false},
482		{"abcß", false},
483		{"abcẞ", false},
484		{"ABCẞ", true},
485		{"tr竪s 端ber", false},
486		{"fooBar", false},
487		{"123ABC", true},
488		{"ABC123", true},
489		{"ABC", true},
490		{"S T R", true},
491		{"fooBar", false},
492		{"abacaba123", false},
493	}
494	for _, test := range tests {
495		actual := IsUpperCase(test.param)
496		if actual != test.expected {
497			t.Errorf("Expected IsUpperCase(%q) to be %v, got %v", test.param, test.expected, actual)
498		}
499	}
500}
501
502func TestHasLowerCase(t *testing.T) {
503	t.Parallel()
504
505	var tests = []struct {
506		param    string
507		expected bool
508	}{
509		{"", true},
510		{"abc123", true},
511		{"abc", true},
512		{"a b c", true},
513		{"abcß", true},
514		{"abcẞ", true},
515		{"ABCẞ", false},
516		{"tr竪s 端ber", true},
517		{"fooBar", true},
518		{"123ABC", false},
519		{"ABC123", false},
520		{"ABC", false},
521		{"S T R", false},
522		{"fooBar", true},
523		{"abacaba123", true},
524		{"FÒÔBÀŘ", false},
525		{"fòôbàř", true},
526		{"fÒÔBÀŘ", true},
527	}
528	for _, test := range tests {
529		actual := HasLowerCase(test.param)
530		if actual != test.expected {
531			t.Errorf("Expected HasLowerCase(%q) to be %v, got %v", test.param, test.expected, actual)
532		}
533	}
534}
535
536func TestHasUpperCase(t *testing.T) {
537	t.Parallel()
538
539	var tests = []struct {
540		param    string
541		expected bool
542	}{
543		{"", true},
544		{"abc123", false},
545		{"abc", false},
546		{"a b c", false},
547		{"abcß", false},
548		{"abcẞ", false},
549		{"ABCẞ", true},
550		{"tr竪s 端ber", false},
551		{"fooBar", true},
552		{"123ABC", true},
553		{"ABC123", true},
554		{"ABC", true},
555		{"S T R", true},
556		{"fooBar", true},
557		{"abacaba123", false},
558		{"FÒÔBÀŘ", true},
559		{"fòôbàř", false},
560		{"Fòôbàř", true},
561	}
562	for _, test := range tests {
563		actual := HasUpperCase(test.param)
564		if actual != test.expected {
565			t.Errorf("Expected HasUpperCase(%q) to be %v, got %v", test.param, test.expected, actual)
566		}
567	}
568}
569
570func TestIsInt(t *testing.T) {
571	t.Parallel()
572
573	var tests = []struct {
574		param    string
575		expected bool
576	}{
577		{"-2147483648", true},          //Signed 32 Bit Min Int
578		{"2147483647", true},           //Signed 32 Bit Max Int
579		{"-2147483649", true},          //Signed 32 Bit Min Int - 1
580		{"2147483648", true},           //Signed 32 Bit Max Int + 1
581		{"4294967295", true},           //Unsigned 32 Bit Max Int
582		{"4294967296", true},           //Unsigned 32 Bit Max Int + 1
583		{"-9223372036854775808", true}, //Signed 64 Bit Min Int
584		{"9223372036854775807", true},  //Signed 64 Bit Max Int
585		{"-9223372036854775809", true}, //Signed 64 Bit Min Int - 1
586		{"9223372036854775808", true},  //Signed 64 Bit Max Int + 1
587		{"18446744073709551615", true}, //Unsigned 64 Bit Max Int
588		{"18446744073709551616", true}, //Unsigned 64 Bit Max Int + 1
589		{"", true},
590		{"123", true},
591		{"0", true},
592		{"-0", true},
593		{"+0", true},
594		{"01", false},
595		{"123.123", false},
596		{" ", false},
597		{"000", false},
598	}
599	for _, test := range tests {
600		actual := IsInt(test.param)
601		if actual != test.expected {
602			t.Errorf("Expected IsInt(%q) to be %v, got %v", test.param, test.expected, actual)
603		}
604	}
605}
606
607func TestIsHash(t *testing.T) {
608	t.Parallel()
609
610	var tests = []struct {
611		param    string
612		algo     string
613		expected bool
614	}{
615		{"3ca25ae354e192b26879f651a51d92aa8a34d8d3", "sha1", true},
616		{"3ca25ae354e192b26879f651a51d34d8d3", "sha1", false},
617		{"3ca25ae354e192b26879f651a51d92aa8a34d8d3", "Tiger160", true},
618		{"3ca25ae354e192b26879f651a51d34d8d3", "ripemd160", false},
619		{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898c", "sha256", true},
620		{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha256", false},
621		{"bf547c3fc5841a377eb1519c2890344dbab15c40ae4150b4b34443d2212e5b04aa9d58865bf03d8ae27840fef430b891", "sha384", true},
622		{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha384", false},
623		{"45bc5fa8cb45ee408c04b6269e9f1e1c17090c5ce26ffeeda2af097735b29953ce547e40ff3ad0d120e5361cc5f9cee35ea91ecd4077f3f589b4d439168f91b9", "sha512", true},
624		{"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha512", false},
625		{"46fc0125a148788a3ac1d649566fc04eb84a746f1a6e4fa7", "tiger192", true},
626		{"46fc0125a148788a3ac1d649566fc04eb84a746f1a6$$%@^", "TIGER192", false},
627		{"46fc0125a148788a3ac1d649566fc04eb84a746f1a6$$%@^", "SOMEHASH", false},
628	}
629	for _, test := range tests {
630		actual := IsHash(test.param, test.algo)
631		if actual != test.expected {
632			t.Errorf("Expected IsHash(%q, %q) to be %v, got %v", test.param, test.algo, test.expected, actual)
633		}
634	}
635}
636
637func TestIsExistingEmail(t *testing.T) {
638	t.Parallel()
639
640	var tests = []struct {
641		param    string
642		expected bool
643	}{
644		{"", false},
645		{"foo@bar.com", true},
646		{"foo@bar.com.au", true},
647		{"foo+bar@bar.com", true},
648		{"foo@bar.coffee", true},
649		{"foo@bar.coffee..coffee", false},
650		{"invalidemail@", false},
651		{"invalid.com", false},
652		{"@invalid.com", false},
653		{"NathAn.daVIeS@DomaIn.cOM", true},
654		{"NATHAN.DAVIES@DOMAIN.CO.UK", true},
655	}
656	for _, test := range tests {
657		actual := IsExistingEmail(test.param)
658		if actual != test.expected {
659			t.Errorf("Expected IsExistingEmail(%q) to be %v, got %v", test.param, test.expected, actual)
660		}
661	}
662}
663
664func TestIsEmail(t *testing.T) {
665	t.Parallel()
666
667	var tests = []struct {
668		param    string
669		expected bool
670	}{
671		{"", false},
672		{"foo@bar.com", true},
673		{"x@x.x", true},
674		{"foo@bar.com.au", true},
675		{"foo+bar@bar.com", true},
676		{"foo@bar.coffee", true},
677		{"foo@bar.coffee..coffee", false},
678		{"foo@bar.bar.coffee", true},
679		{"foo@bar.中文网", true},
680		{"invalidemail@", false},
681		{"invalid.com", false},
682		{"@invalid.com", false},
683		{"test|123@m端ller.com", true},
684		{"hans@m端ller.com", true},
685		{"hans.m端ller@test.com", true},
686		{"NathAn.daVIeS@DomaIn.cOM", true},
687		{"NATHAN.DAVIES@DOMAIN.CO.UK", true},
688	}
689	for _, test := range tests {
690		actual := IsEmail(test.param)
691		if actual != test.expected {
692			t.Errorf("Expected IsEmail(%q) to be %v, got %v", test.param, test.expected, actual)
693		}
694	}
695}
696
697func TestIsURL(t *testing.T) {
698	t.Parallel()
699
700	var tests = []struct {
701		param    string
702		expected bool
703	}{
704		{"", false},
705		{"http://foo.bar#com", true},
706		{"http://foobar.com", true},
707		{"https://foobar.com", true},
708		{"foobar.com", true},
709		{"http://foobar.coffee/", true},
710		{"http://foobar.中文网/", true},
711		{"http://foobar.org/", true},
712		{"http://foobar.ORG", true},
713		{"http://foobar.org:8080/", true},
714		{"ftp://foobar.ru/", true},
715		{"ftp.foo.bar", true},
716		{"http://user:pass@www.foobar.com/", true},
717		{"http://user:pass@www.foobar.com/path/file", true},
718		{"http://127.0.0.1/", true},
719		{"http://duckduckgo.com/?q=%2F", true},
720		{"http://localhost:3000/", true},
721		{"http://foobar.com/?foo=bar#baz=qux", true},
722		{"http://foobar.com?foo=bar", true},
723		{"http://www.xn--froschgrn-x9a.net/", true},
724		{"http://foobar.com/a-", true},
725		{"http://foobar.پاکستان/", true},
726		{"http://foobar.c_o_m", false},
727		{"http://_foobar.com", false},
728		{"http://foo_bar.com", true},
729		{"http://user:pass@foo_bar_bar.bar_foo.com", true},
730		{"", false},
731		{"xyz://foobar.com", false},
732		// {"invalid.", false}, is it false like "localhost."?
733		{".com", false},
734		{"rtmp://foobar.com", false},
735		{"http://localhost:3000/", true},
736		{"http://foobar.com#baz=qux", true},
737		{"http://foobar.com/t$-_.+!*\\'(),", true},
738		{"http://www.foobar.com/~foobar", true},
739		{"http://www.-foobar.com/", false},
740		{"http://www.foo---bar.com/", false},
741		{"http://r6---snnvoxuioq6.googlevideo.com", true},
742		{"mailto:someone@example.com", true},
743		{"irc://irc.server.org/channel", false},
744		{"irc://#channel@network", true},
745		{"/abs/test/dir", false},
746		{"./rel/test/dir", false},
747		{"http://foo^bar.org", false},
748		{"http://foo&*bar.org", false},
749		{"http://foo&bar.org", false},
750		{"http://foo bar.org", false},
751		{"http://foo.bar.org", true},
752		{"http://www.foo.bar.org", true},
753		{"http://www.foo.co.uk", true},
754		{"foo", false},
755		{"http://.foo.com", false},
756		{"http://,foo.com", false},
757		{",foo.com", false},
758		{"http://myservice.:9093/", true},
759		// according to issues #62 #66
760		{"https://pbs.twimg.com/profile_images/560826135676588032/j8fWrmYY_normal.jpeg", true},
761		// according to #125
762		{"http://prometheus-alertmanager.service.q:9093", true},
763		{"aio1_alertmanager_container-63376c45:9093", true},
764		{"https://www.logn-123-123.url.with.sigle.letter.d:12345/url/path/foo?bar=zzz#user", true},
765		{"http://me.example.com", true},
766		{"http://www.me.example.com", true},
767		{"https://farm6.static.flickr.com", true},
768		{"https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5", true},
769		{"google", false},
770		// According to #87
771		{"http://hyphenated-host-name.example.co.in", true},
772		{"http://cant-end-with-hyphen-.example.com", false},
773		{"http://-cant-start-with-hyphen.example.com", false},
774		{"http://www.domain-can-have-dashes.com", true},
775		{"http://m.abcd.com/test.html", true},
776		{"http://m.abcd.com/a/b/c/d/test.html?args=a&b=c", true},
777		{"http://[::1]:9093", true},
778		{"http://[::1]:909388", false},
779		{"1200::AB00:1234::2552:7777:1313", false},
780		{"http://[2001:db8:a0b:12f0::1]/index.html", true},
781		{"http://[1200:0000:AB00:1234:0000:2552:7777:1313]", true},
782		{"http://user:pass@[::1]:9093/a/b/c/?a=v#abc", true},
783		{"https://127.0.0.1/a/b/c?a=v&c=11d", true},
784		{"https://foo_bar.example.com", true},
785		{"http://foo_bar.example.com", true},
786		{"http://foo_bar_fizz_buzz.example.com", true},
787		{"http://_cant_start_with_underescore", false},
788		{"http://cant_end_with_underescore_", false},
789		{"foo_bar.example.com", true},
790		{"foo_bar_fizz_buzz.example.com", true},
791		{"http://hello_world.example.com", true},
792		// According to #212
793		{"foo_bar-fizz-buzz:1313", true},
794		{"foo_bar-fizz-buzz:13:13", false},
795		{"foo_bar-fizz-buzz://1313", false},
796	}
797	for _, test := range tests {
798		actual := IsURL(test.param)
799		if actual != test.expected {
800			t.Errorf("Expected IsURL(%q) to be %v, got %v", test.param, test.expected, actual)
801		}
802	}
803}
804
805func TestIsRequestURL(t *testing.T) {
806	t.Parallel()
807
808	var tests = []struct {
809		param    string
810		expected bool
811	}{
812		{"", false},
813		{"http://foo.bar/#com", true},
814		{"http://foobar.com", true},
815		{"https://foobar.com", true},
816		{"foobar.com", false},
817		{"http://foobar.coffee/", true},
818		{"http://foobar.中文网/", true},
819		{"http://foobar.org/", true},
820		{"http://foobar.org:8080/", true},
821		{"ftp://foobar.ru/", true},
822		{"http://user:pass@www.foobar.com/", true},
823		{"http://127.0.0.1/", true},
824		{"http://duckduckgo.com/?q=%2F", true},
825		{"http://localhost:3000/", true},
826		{"http://foobar.com/?foo=bar#baz=qux", true},
827		{"http://foobar.com?foo=bar", true},
828		{"http://www.xn--froschgrn-x9a.net/", true},
829		{"", false},
830		{"xyz://foobar.com", true},
831		{"invalid.", false},
832		{".com", false},
833		{"rtmp://foobar.com", true},
834		{"http://www.foo_bar.com/", true},
835		{"http://localhost:3000/", true},
836		{"http://foobar.com/#baz=qux", true},
837		{"http://foobar.com/t$-_.+!*\\'(),", true},
838		{"http://www.foobar.com/~foobar", true},
839		{"http://www.-foobar.com/", true},
840		{"http://www.foo---bar.com/", true},
841		{"mailto:someone@example.com", true},
842		{"irc://irc.server.org/channel", true},
843		{"/abs/test/dir", false},
844		{"./rel/test/dir", false},
845	}
846	for _, test := range tests {
847		actual := IsRequestURL(test.param)
848		if actual != test.expected {
849			t.Errorf("Expected IsRequestURL(%q) to be %v, got %v", test.param, test.expected, actual)
850		}
851	}
852}
853
854func TestIsRequestURI(t *testing.T) {
855	t.Parallel()
856
857	var tests = []struct {
858		param    string
859		expected bool
860	}{
861		{"", false},
862		{"http://foo.bar/#com", true},
863		{"http://foobar.com", true},
864		{"https://foobar.com", true},
865		{"foobar.com", false},
866		{"http://foobar.coffee/", true},
867		{"http://foobar.中文网/", true},
868		{"http://foobar.org/", true},
869		{"http://foobar.org:8080/", true},
870		{"ftp://foobar.ru/", true},
871		{"http://user:pass@www.foobar.com/", true},
872		{"http://127.0.0.1/", true},
873		{"http://duckduckgo.com/?q=%2F", true},
874		{"http://localhost:3000/", true},
875		{"http://foobar.com/?foo=bar#baz=qux", true},
876		{"http://foobar.com?foo=bar", true},
877		{"http://www.xn--froschgrn-x9a.net/", true},
878		{"xyz://foobar.com", true},
879		{"invalid.", false},
880		{".com", false},
881		{"rtmp://foobar.com", true},
882		{"http://www.foo_bar.com/", true},
883		{"http://localhost:3000/", true},
884		{"http://foobar.com/#baz=qux", true},
885		{"http://foobar.com/t$-_.+!*\\'(),", true},
886		{"http://www.foobar.com/~foobar", true},
887		{"http://www.-foobar.com/", true},
888		{"http://www.foo---bar.com/", true},
889		{"mailto:someone@example.com", true},
890		{"irc://irc.server.org/channel", true},
891		{"/abs/test/dir", true},
892		{"./rel/test/dir", false},
893	}
894	for _, test := range tests {
895		actual := IsRequestURI(test.param)
896		if actual != test.expected {
897			t.Errorf("Expected IsRequestURI(%q) to be %v, got %v", test.param, test.expected, actual)
898		}
899	}
900}
901
902func TestIsFloat(t *testing.T) {
903	t.Parallel()
904
905	var tests = []struct {
906		param    string
907		expected bool
908	}{
909		{"", false},
910		{"  ", false},
911		{"-.123", false},
912		{"abacaba", false},
913		{"1f", false},
914		{"-1f", false},
915		{"+1f", false},
916		{"123", true},
917		{"123.", true},
918		{"123.123", true},
919		{"-123.123", true},
920		{"+123.123", true},
921		{"0.123", true},
922		{"-0.123", true},
923		{"+0.123", true},
924		{".0", true},
925		{"01.123", true},
926		{"-0.22250738585072011e-307", true},
927		{"+0.22250738585072011e-307", true},
928	}
929	for _, test := range tests {
930		actual := IsFloat(test.param)
931		if actual != test.expected {
932			t.Errorf("Expected IsFloat(%q) to be %v, got %v", test.param, test.expected, actual)
933		}
934	}
935}
936
937func TestIsHexadecimal(t *testing.T) {
938	t.Parallel()
939
940	var tests = []struct {
941		param    string
942		expected bool
943	}{
944		{"abcdefg", false},
945		{"", false},
946		{"..", false},
947		{"deadBEEF", true},
948		{"ff0044", true},
949	}
950	for _, test := range tests {
951		actual := IsHexadecimal(test.param)
952		if actual != test.expected {
953			t.Errorf("Expected IsHexadecimal(%q) to be %v, got %v", test.param, test.expected, actual)
954		}
955	}
956}
957
958func TestIsHexcolor(t *testing.T) {
959	t.Parallel()
960
961	var tests = []struct {
962		param    string
963		expected bool
964	}{
965		{"", false},
966		{"#ff", false},
967		{"fff0", false},
968		{"#ff12FG", false},
969		{"CCccCC", true},
970		{"fff", true},
971		{"#f00", true},
972	}
973	for _, test := range tests {
974		actual := IsHexcolor(test.param)
975		if actual != test.expected {
976			t.Errorf("Expected IsHexcolor(%q) to be %v, got %v", test.param, test.expected, actual)
977		}
978	}
979}
980
981func TestIsRGBcolor(t *testing.T) {
982	t.Parallel()
983
984	var tests = []struct {
985		param    string
986		expected bool
987	}{
988		{"", false},
989		{"rgb(0,31,255)", true},
990		{"rgb(1,349,275)", false},
991		{"rgb(01,31,255)", false},
992		{"rgb(0.6,31,255)", false},
993		{"rgba(0,31,255)", false},
994		{"rgb(0,  31, 255)", true},
995	}
996	for _, test := range tests {
997		actual := IsRGBcolor(test.param)
998		if actual != test.expected {
999			t.Errorf("Expected IsRGBcolor(%q) to be %v, got %v", test.param, test.expected, actual)
1000		}
1001	}
1002}
1003
1004func TestIsNull(t *testing.T) {
1005	t.Parallel()
1006
1007	var tests = []struct {
1008		param    string
1009		expected bool
1010	}{
1011		{"abacaba", false},
1012		{"", true},
1013	}
1014	for _, test := range tests {
1015		actual := IsNull(test.param)
1016		if actual != test.expected {
1017			t.Errorf("Expected IsNull(%q) to be %v, got %v", test.param, test.expected, actual)
1018		}
1019	}
1020}
1021
1022func TestHasWhitespaceOnly(t *testing.T) {
1023    t.Parallel()
1024
1025    var tests = []struct {
1026        param    string
1027        expected bool
1028    }{
1029        {"abacaba", false},
1030        {"", false},
1031        {"    ", true},
1032        {"  \r\n  ", true},
1033        {"\014\012\011\013\015", true},
1034        {"\014\012\011\013 abc  \015", false},
1035        {"\f\n\t\v\r\f", true},
1036        {"x\n\t\t\t\t", false},
1037        {"\f\n\t  \n\n\n   \v\r\f", true},
1038    }
1039    for _, test := range tests {
1040        actual := HasWhitespaceOnly(test.param)
1041        if actual != test.expected {
1042            t.Errorf("Expected HasWhitespaceOnly(%q) to be %v, got %v", test.param, test.expected, actual)
1043        }
1044    }
1045}
1046
1047func TestHasWhitespace(t *testing.T) {
1048    t.Parallel()
1049
1050    var tests = []struct {
1051        param    string
1052        expected bool
1053    }{
1054        {"abacaba", false},
1055        {"", false},
1056        {"    ", true},
1057        {"  \r\n  ", true},
1058        {"\014\012\011\013\015", true},
1059        {"\014\012\011\013 abc  \015", true},
1060        {"\f\n\t\v\r\f", true},
1061        {"x\n\t\t\t\t", true},
1062        {"\f\n\t  \n\n\n   \v\r\f", true},
1063    }
1064    for _, test := range tests {
1065        actual := HasWhitespace(test.param)
1066        if actual != test.expected {
1067            t.Errorf("Expected HasWhitespace(%q) to be %v, got %v", test.param, test.expected, actual)
1068        }
1069    }
1070}
1071
1072func TestIsDivisibleBy(t *testing.T) {
1073	t.Parallel()
1074
1075	var tests = []struct {
1076		param1   string
1077		param2   string
1078		expected bool
1079	}{
1080		{"4", "2", true},
1081		{"100", "10", true},
1082		{"", "1", true},
1083		{"123", "foo", false},
1084		{"123", "0", false},
1085	}
1086	for _, test := range tests {
1087		actual := IsDivisibleBy(test.param1, test.param2)
1088		if actual != test.expected {
1089			t.Errorf("Expected IsDivisibleBy(%q, %q) to be %v, got %v", test.param1, test.param2, test.expected, actual)
1090		}
1091	}
1092}
1093
1094// This small example illustrate how to work with IsDivisibleBy function.
1095func ExampleIsDivisibleBy() {
1096	println("1024 is divisible by 64: ", IsDivisibleBy("1024", "64"))
1097}
1098
1099func TestIsByteLength(t *testing.T) {
1100	t.Parallel()
1101
1102	var tests = []struct {
1103		param1   string
1104		param2   int
1105		param3   int
1106		expected bool
1107	}{
1108		{"abacaba", 100, -1, false},
1109		{"abacaba", 1, 3, false},
1110		{"abacaba", 1, 7, true},
1111		{"abacaba", 0, 8, true},
1112		{"\ufff0", 1, 1, false},
1113	}
1114	for _, test := range tests {
1115		actual := IsByteLength(test.param1, test.param2, test.param3)
1116		if actual != test.expected {
1117			t.Errorf("Expected IsByteLength(%q, %q, %q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual)
1118		}
1119	}
1120}
1121
1122func TestIsJSON(t *testing.T) {
1123	t.Parallel()
1124
1125	var tests = []struct {
1126		param    string
1127		expected bool
1128	}{
1129		{"", false},
1130		{"145", true},
1131		{"asdf", false},
1132		{"123:f00", false},
1133		{"{\"Name\":\"Alice\",\"Body\":\"Hello\",\"Time\":1294706395881547000}", true},
1134		{"{}", true},
1135		{"{\"Key\":{\"Key\":{\"Key\":123}}}", true},
1136		{"[]", true},
1137		{"null", true},
1138	}
1139	for _, test := range tests {
1140		actual := IsJSON(test.param)
1141		if actual != test.expected {
1142			t.Errorf("Expected IsJSON(%q) to be %v, got %v", test.param, test.expected, actual)
1143		}
1144	}
1145}
1146
1147func TestIsMultibyte(t *testing.T) {
1148	t.Parallel()
1149
1150	var tests = []struct {
1151		param    string
1152		expected bool
1153	}{
1154		{"abc", false},
1155		{"123", false},
1156		{"<>@;.-=", false},
1157		{"ひらがな・カタカナ、.漢字", true},
1158		{"あいうえお foobar", true},
1159		{"test@example.com", true},
1160		{"test@example.com", true},
1161		{"1234abcDExyz", true},
1162		{"カタカナ", true},
1163		{"", true},
1164	}
1165	for _, test := range tests {
1166		actual := IsMultibyte(test.param)
1167		if actual != test.expected {
1168			t.Errorf("Expected IsMultibyte(%q) to be %v, got %v", test.param, test.expected, actual)
1169		}
1170	}
1171}
1172
1173func TestIsASCII(t *testing.T) {
1174	t.Parallel()
1175
1176	var tests = []struct {
1177		param    string
1178		expected bool
1179	}{
1180		{"", true},
1181		{"foobar", false},
1182		{"xyz098", false},
1183		{"123456", false},
1184		{"カタカナ", false},
1185		{"foobar", true},
1186		{"0987654321", true},
1187		{"test@example.com", true},
1188		{"1234abcDEF", true},
1189		{"", true},
1190	}
1191	for _, test := range tests {
1192		actual := IsASCII(test.param)
1193		if actual != test.expected {
1194			t.Errorf("Expected IsASCII(%q) to be %v, got %v", test.param, test.expected, actual)
1195		}
1196	}
1197}
1198
1199func TestIsPrintableASCII(t *testing.T) {
1200	t.Parallel()
1201
1202	var tests = []struct {
1203		param    string
1204		expected bool
1205	}{
1206		{"", true},
1207		{"foobar", false},
1208		{"xyz098", false},
1209		{"123456", false},
1210		{"カタカナ", false},
1211		{"foobar", true},
1212		{"0987654321", true},
1213		{"test@example.com", true},
1214		{"1234abcDEF", true},
1215		{"newline\n", false},
1216		{"\x19test\x7F", false},
1217	}
1218	for _, test := range tests {
1219		actual := IsPrintableASCII(test.param)
1220		if actual != test.expected {
1221			t.Errorf("Expected IsPrintableASCII(%q) to be %v, got %v", test.param, test.expected, actual)
1222		}
1223	}
1224}
1225
1226func TestIsFullWidth(t *testing.T) {
1227	t.Parallel()
1228
1229	var tests = []struct {
1230		param    string
1231		expected bool
1232	}{
1233		{"", true},
1234		{"abc", false},
1235		{"abc123", false},
1236		{"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false},
1237		{"ひらがな・カタカナ、.漢字", true},
1238		{"3ー0 a@com", true},
1239		{"Fカタカナ゙ᆲ", true},
1240		{"Good=Parts", true},
1241		{"", true},
1242	}
1243	for _, test := range tests {
1244		actual := IsFullWidth(test.param)
1245		if actual != test.expected {
1246			t.Errorf("Expected IsFullWidth(%q) to be %v, got %v", test.param, test.expected, actual)
1247		}
1248	}
1249}
1250
1251func TestIsHalfWidth(t *testing.T) {
1252	t.Parallel()
1253
1254	var tests = []struct {
1255		param    string
1256		expected bool
1257	}{
1258		{"", true},
1259		{"あいうえお", false},
1260		{"0011", false},
1261		{"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", true},
1262		{"l-btn_02--active", true},
1263		{"abc123い", true},
1264		{"カタカナ゙ᆲ←", true},
1265		{"", true},
1266	}
1267	for _, test := range tests {
1268		actual := IsHalfWidth(test.param)
1269		if actual != test.expected {
1270			t.Errorf("Expected IsHalfWidth(%q) to be %v, got %v", test.param, test.expected, actual)
1271		}
1272	}
1273}
1274
1275func TestIsVariableWidth(t *testing.T) {
1276	t.Parallel()
1277
1278	var tests = []struct {
1279		param    string
1280		expected bool
1281	}{
1282		{"", true},
1283		{"ひらがなカタカナ漢字ABCDE", true},
1284		{"3ー0123", true},
1285		{"Fカタカナ゙ᆲ", true},
1286		{"", true},
1287		{"Good=Parts", true},
1288		{"abc", false},
1289		{"abc123", false},
1290		{"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false},
1291		{"ひらがな・カタカナ、.漢字", false},
1292		{"123456", false},
1293		{"カタカナ゙ᆲ", false},
1294	}
1295	for _, test := range tests {
1296		actual := IsVariableWidth(test.param)
1297		if actual != test.expected {
1298			t.Errorf("Expected IsVariableWidth(%q) to be %v, got %v", test.param, test.expected, actual)
1299		}
1300	}
1301}
1302
1303func TestIsUUID(t *testing.T) {
1304	t.Parallel()
1305
1306	// Tests without version
1307	var tests = []struct {
1308		param    string
1309		expected bool
1310	}{
1311		{"", false},
1312		{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
1313		{"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false},
1314		{"a987fbc94bed3078cf079141ba07c9f3", false},
1315		{"934859", false},
1316		{"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false},
1317		{"aaaaaaaa-1111-1111-aaag-111111111111", false},
1318		{"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
1319	}
1320	for _, test := range tests {
1321		actual := IsUUID(test.param)
1322		if actual != test.expected {
1323			t.Errorf("Expected IsUUID(%q) to be %v, got %v", test.param, test.expected, actual)
1324		}
1325	}
1326
1327	// UUID ver. 3
1328	tests = []struct {
1329		param    string
1330		expected bool
1331	}{
1332		{"", false},
1333		{"412452646", false},
1334		{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
1335		{"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false},
1336		{"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true},
1337	}
1338	for _, test := range tests {
1339		actual := IsUUIDv3(test.param)
1340		if actual != test.expected {
1341			t.Errorf("Expected IsUUIDv3(%q) to be %v, got %v", test.param, test.expected, actual)
1342		}
1343	}
1344
1345	// UUID ver. 4
1346	tests = []struct {
1347		param    string
1348		expected bool
1349	}{
1350		{"", false},
1351		{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
1352		{"a987fbc9-4bed-5078-af07-9141ba07c9f3", false},
1353		{"934859", false},
1354		{"57b73598-8764-4ad0-a76a-679bb6640eb1", true},
1355		{"625e63f3-58f5-40b7-83a1-a72ad31acffb", true},
1356	}
1357	for _, test := range tests {
1358		actual := IsUUIDv4(test.param)
1359		if actual != test.expected {
1360			t.Errorf("Expected IsUUIDv4(%q) to be %v, got %v", test.param, test.expected, actual)
1361		}
1362	}
1363
1364	// UUID ver. 5
1365	tests = []struct {
1366		param    string
1367		expected bool
1368	}{
1369
1370		{"", false},
1371		{"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
1372		{"9c858901-8a57-4791-81fe-4c455b099bc9", false},
1373		{"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false},
1374		{"987fbc97-4bed-5078-af07-9141ba07c9f3", true},
1375		{"987fbc97-4bed-5078-9f07-9141ba07c9f3", true},
1376	}
1377	for _, test := range tests {
1378		actual := IsUUIDv5(test.param)
1379		if actual != test.expected {
1380			t.Errorf("Expected IsUUIDv5(%q) to be %v, got %v", test.param, test.expected, actual)
1381		}
1382	}
1383}
1384
1385func TestIsCreditCard(t *testing.T) {
1386	t.Parallel()
1387
1388	var tests = []struct {
1389		param    string
1390		expected bool
1391	}{
1392		{"", false},
1393		{"foo", false},
1394		{"5398228707871528", false},
1395		{"375556917985515", true},
1396		{"36050234196908", true},
1397		{"4716461583322103", true},
1398		{"4716-2210-5188-5662", true},
1399		{"4929 7226 5379 7141", true},
1400		{"5398228707871527", true},
1401	}
1402	for _, test := range tests {
1403		actual := IsCreditCard(test.param)
1404		if actual != test.expected {
1405			t.Errorf("Expected IsCreditCard(%q) to be %v, got %v", test.param, test.expected, actual)
1406		}
1407	}
1408}
1409
1410func TestIsISBN(t *testing.T) {
1411	t.Parallel()
1412
1413	// Without version
1414	var tests = []struct {
1415		param    string
1416		expected bool
1417	}{
1418		{"", false},
1419		{"foo", false},
1420		{"3836221195", true},
1421		{"1-61729-085-8", true},
1422		{"3 423 21412 0", true},
1423		{"3 401 01319 X", true},
1424		{"9784873113685", true},
1425		{"978-4-87311-368-5", true},
1426		{"978 3401013190", true},
1427		{"978-3-8362-2119-1", true},
1428	}
1429	for _, test := range tests {
1430		actual := IsISBN(test.param, -1)
1431		if actual != test.expected {
1432			t.Errorf("Expected IsISBN(%q, -1) to be %v, got %v", test.param, test.expected, actual)
1433		}
1434	}
1435
1436	// ISBN 10
1437	tests = []struct {
1438		param    string
1439		expected bool
1440	}{
1441		{"", false},
1442		{"foo", false},
1443		{"3423214121", false},
1444		{"978-3836221191", false},
1445		{"3-423-21412-1", false},
1446		{"3 423 21412 1", false},
1447		{"3836221195", true},
1448		{"1-61729-085-8", true},
1449		{"3 423 21412 0", true},
1450		{"3 401 01319 X", true},
1451	}
1452	for _, test := range tests {
1453		actual := IsISBN10(test.param)
1454		if actual != test.expected {
1455			t.Errorf("Expected IsISBN10(%q) to be %v, got %v", test.param, test.expected, actual)
1456		}
1457	}
1458
1459	// ISBN 13
1460	tests = []struct {
1461		param    string
1462		expected bool
1463	}{
1464		{"", false},
1465		{"foo", false},
1466		{"3-8362-2119-5", false},
1467		{"01234567890ab", false},
1468		{"978 3 8362 2119 0", false},
1469		{"9784873113685", true},
1470		{"978-4-87311-368-5", true},
1471		{"978 3401013190", true},
1472		{"978-3-8362-2119-1", true},
1473	}
1474	for _, test := range tests {
1475		actual := IsISBN13(test.param)
1476		if actual != test.expected {
1477			t.Errorf("Expected IsISBN13(%q) to be %v, got %v", test.param, test.expected, actual)
1478		}
1479	}
1480}
1481
1482func TestIsDataURI(t *testing.T) {
1483	t.Parallel()
1484
1485	var tests = []struct {
1486		param    string
1487		expected bool
1488	}{
1489		{"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true},
1490		{"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true},
1491		{"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
1492		{"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" +
1493			"UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" +
1494			"rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" +
1495			"FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" +
1496			"QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" +
1497			"Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true},
1498		{"data:image/png;base64,12345", false},
1499		{"", false},
1500		{"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false},
1501	}
1502	for _, test := range tests {
1503		actual := IsDataURI(test.param)
1504		if actual != test.expected {
1505			t.Errorf("Expected IsDataURI(%q) to be %v, got %v", test.param, test.expected, actual)
1506		}
1507	}
1508}
1509
1510func TestIsBase64(t *testing.T) {
1511	t.Parallel()
1512
1513	var tests = []struct {
1514		param    string
1515		expected bool
1516	}{
1517		{"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true},
1518		{"Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true},
1519		{"U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", true},
1520		{"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" +
1521			"UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" +
1522			"rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" +
1523			"FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" +
1524			"QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" +
1525			"Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true},
1526		{"12345", false},
1527		{"", false},
1528		{"Vml2YW11cyBmZXJtZtesting123", false},
1529	}
1530	for _, test := range tests {
1531		actual := IsBase64(test.param)
1532		if actual != test.expected {
1533			t.Errorf("Expected IsBase64(%q) to be %v, got %v", test.param, test.expected, actual)
1534		}
1535	}
1536}
1537
1538func TestIsISO3166Alpha2(t *testing.T) {
1539	t.Parallel()
1540
1541	var tests = []struct {
1542		param    string
1543		expected bool
1544	}{
1545		{"", false},
1546		{"ABCD", false},
1547		{"A", false},
1548		{"AC", false},
1549		{"AP", false},
1550		{"GER", false},
1551		{"NU", true},
1552		{"DE", true},
1553		{"JP", true},
1554		{"JPN", false},
1555		{"ZWE", false},
1556		{"GER", false},
1557		{"DEU", false},
1558	}
1559	for _, test := range tests {
1560		actual := IsISO3166Alpha2(test.param)
1561		if actual != test.expected {
1562			t.Errorf("Expected IsISO3166Alpha2(%q) to be %v, got %v", test.param, test.expected, actual)
1563		}
1564	}
1565}
1566
1567func TestIsISO3166Alpha3(t *testing.T) {
1568	t.Parallel()
1569
1570	var tests = []struct {
1571		param    string
1572		expected bool
1573	}{
1574		{"", false},
1575		{"ABCD", false},
1576		{"A", false},
1577		{"AC", false},
1578		{"AP", false},
1579		{"NU", false},
1580		{"DE", false},
1581		{"JP", false},
1582		{"ZWE", true},
1583		{"JPN", true},
1584		{"GER", false},
1585		{"DEU", true},
1586	}
1587	for _, test := range tests {
1588		actual := IsISO3166Alpha3(test.param)
1589		if actual != test.expected {
1590			t.Errorf("Expected IsISO3166Alpha3(%q) to be %v, got %v", test.param, test.expected, actual)
1591		}
1592	}
1593}
1594
1595func TestIsISO693Alpha2(t *testing.T) {
1596	t.Parallel()
1597
1598	var tests = []struct {
1599		param    string
1600		expected bool
1601	}{
1602		{"", false},
1603		{"abcd", false},
1604		{"a", false},
1605		{"ac", false},
1606		{"ap", false},
1607		{"de", true},
1608		{"DE", false},
1609		{"mk", true},
1610		{"mac", false},
1611		{"sw", true},
1612		{"SW", false},
1613		{"ger", false},
1614		{"deu", false},
1615	}
1616	for _, test := range tests {
1617		actual := IsISO693Alpha2(test.param)
1618		if actual != test.expected {
1619			t.Errorf("Expected IsISO693Alpha2(%q) to be %v, got %v", test.param, test.expected, actual)
1620		}
1621	}
1622}
1623
1624func TestIsISO693Alpha3b(t *testing.T) {
1625	t.Parallel()
1626
1627	var tests = []struct {
1628		param    string
1629		expected bool
1630	}{
1631		{"", false},
1632		{"abcd", false},
1633		{"a", false},
1634		{"ac", false},
1635		{"ap", false},
1636		{"de", false},
1637		{"DE", false},
1638		{"mkd", false},
1639		{"mac", true},
1640		{"sw", false},
1641		{"SW", false},
1642		{"ger", true},
1643		{"deu", false},
1644	}
1645	for _, test := range tests {
1646		actual := IsISO693Alpha3b(test.param)
1647		if actual != test.expected {
1648			t.Errorf("Expected IsISO693Alpha3b(%q) to be %v, got %v", test.param, test.expected, actual)
1649		}
1650	}
1651}
1652
1653func TestIsIP(t *testing.T) {
1654	t.Parallel()
1655
1656	// Without version
1657	var tests = []struct {
1658		param    string
1659		expected bool
1660	}{
1661		{"", false},
1662		{"127.0.0.1", true},
1663		{"0.0.0.0", true},
1664		{"255.255.255.255", true},
1665		{"1.2.3.4", true},
1666		{"::1", true},
1667		{"2001:db8:0000:1:1:1:1:1", true},
1668		{"300.0.0.0", false},
1669	}
1670	for _, test := range tests {
1671		actual := IsIP(test.param)
1672		if actual != test.expected {
1673			t.Errorf("Expected IsIP(%q) to be %v, got %v", test.param, test.expected, actual)
1674		}
1675	}
1676
1677	// IPv4
1678	tests = []struct {
1679		param    string
1680		expected bool
1681	}{
1682		{"", false},
1683		{"127.0.0.1", true},
1684		{"0.0.0.0", true},
1685		{"255.255.255.255", true},
1686		{"1.2.3.4", true},
1687		{"::1", false},
1688		{"2001:db8:0000:1:1:1:1:1", false},
1689		{"300.0.0.0", false},
1690	}
1691	for _, test := range tests {
1692		actual := IsIPv4(test.param)
1693		if actual != test.expected {
1694			t.Errorf("Expected IsIPv4(%q) to be %v, got %v", test.param, test.expected, actual)
1695		}
1696	}
1697
1698	// IPv6
1699	tests = []struct {
1700		param    string
1701		expected bool
1702	}{
1703		{"", false},
1704		{"127.0.0.1", false},
1705		{"0.0.0.0", false},
1706		{"255.255.255.255", false},
1707		{"1.2.3.4", false},
1708		{"::1", true},
1709		{"2001:db8:0000:1:1:1:1:1", true},
1710		{"300.0.0.0", false},
1711	}
1712	for _, test := range tests {
1713		actual := IsIPv6(test.param)
1714		if actual != test.expected {
1715			t.Errorf("Expected IsIPv6(%q) to be %v, got %v", test.param, test.expected, actual)
1716		}
1717	}
1718}
1719
1720func TestIsPort(t *testing.T) {
1721	t.Parallel()
1722
1723	var tests = []struct {
1724		param    string
1725		expected bool
1726	}{
1727		{"1", true},
1728		{"65535", true},
1729		{"0", false},
1730		{"65536", false},
1731		{"65538", false},
1732	}
1733
1734	for _, test := range tests {
1735		actual := IsPort(test.param)
1736		if actual != test.expected {
1737			t.Errorf("Expected IsPort(%q) to be %v, got %v", test.param, test.expected, actual)
1738		}
1739	}
1740}
1741
1742func TestIsDNSName(t *testing.T) {
1743	t.Parallel()
1744
1745	var tests = []struct {
1746		param    string
1747		expected bool
1748	}{
1749		{"localhost", true},
1750		{"a.bc", true},
1751		{"a.b.", true},
1752		{"a.b..", false},
1753		{"localhost.local", true},
1754		{"localhost.localdomain.intern", true},
1755		{"l.local.intern", true},
1756		{"ru.link.n.svpncloud.com", true},
1757		{"-localhost", false},
1758		{"localhost.-localdomain", false},
1759		{"localhost.localdomain.-int", false},
1760		{"_localhost", true},
1761		{"localhost._localdomain", true},
1762		{"localhost.localdomain._int", true},
1763		{"lÖcalhost", false},
1764		{"localhost.lÖcaldomain", false},
1765		{"localhost.localdomain.üntern", false},
1766		{"__", true},
1767		{"localhost/", false},
1768		{"127.0.0.1", false},
1769		{"[::1]", false},
1770		{"50.50.50.50", false},
1771		{"localhost.localdomain.intern:65535", false},
1772		{"漢字汉字", false},
1773		{"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de", false},
1774	}
1775
1776	for _, test := range tests {
1777		actual := IsDNSName(test.param)
1778		if actual != test.expected {
1779			t.Errorf("Expected IsDNS(%q) to be %v, got %v", test.param, test.expected, actual)
1780		}
1781	}
1782}
1783
1784func TestIsHost(t *testing.T) {
1785	t.Parallel()
1786	var tests = []struct {
1787		param    string
1788		expected bool
1789	}{
1790		{"localhost", true},
1791		{"localhost.localdomain", true},
1792		{"2001:db8:0000:1:1:1:1:1", true},
1793		{"::1", true},
1794		{"play.golang.org", true},
1795		{"localhost.localdomain.intern:65535", false},
1796		{"-[::1]", false},
1797		{"-localhost", false},
1798		{".localhost", false},
1799	}
1800	for _, test := range tests {
1801		actual := IsHost(test.param)
1802		if actual != test.expected {
1803			t.Errorf("Expected IsHost(%q) to be %v, got %v", test.param, test.expected, actual)
1804		}
1805	}
1806
1807}
1808
1809func TestIsDialString(t *testing.T) {
1810	t.Parallel()
1811
1812	var tests = []struct {
1813		param    string
1814		expected bool
1815	}{
1816		{"localhost.local:1", true},
1817		{"localhost.localdomain:9090", true},
1818		{"localhost.localdomain.intern:65535", true},
1819		{"127.0.0.1:30000", true},
1820		{"[::1]:80", true},
1821		{"[1200::AB00:1234::2552:7777:1313]:22", false},
1822		{"-localhost:1", false},
1823		{"localhost.-localdomain:9090", false},
1824		{"localhost.localdomain.-int:65535", false},
1825		{"localhost.loc:100000", false},
1826		{"漢字汉字:2", false},
1827		{"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de:20000", false},
1828	}
1829
1830	for _, test := range tests {
1831		actual := IsDialString(test.param)
1832		if actual != test.expected {
1833			t.Errorf("Expected IsDialString(%q) to be %v, got %v", test.param, test.expected, actual)
1834		}
1835	}
1836}
1837
1838func TestIsMAC(t *testing.T) {
1839	t.Parallel()
1840
1841	var tests = []struct {
1842		param    string
1843		expected bool
1844	}{
1845		{"3D:F2:C9:A6:B3:4F", true},
1846		{"3D-F2-C9-A6-B3:4F", false},
1847		{"123", false},
1848		{"", false},
1849		{"abacaba", false},
1850	}
1851	for _, test := range tests {
1852		actual := IsMAC(test.param)
1853		if actual != test.expected {
1854			t.Errorf("Expected IsMAC(%q) to be %v, got %v", test.param, test.expected, actual)
1855		}
1856	}
1857}
1858
1859func TestFilePath(t *testing.T) {
1860	t.Parallel()
1861
1862	var tests = []struct {
1863		param    string
1864		expected bool
1865		osType   int
1866	}{
1867		{"c:\\" + strings.Repeat("a", 32767), true, Win}, //See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
1868		{"c:\\" + strings.Repeat("a", 32768), false, Win},
1869		{"c:\\path\\file (x86)\bar", true, Win},
1870		{"c:\\path\\file", true, Win},
1871		{"c:\\path\\file:exe", false, Unknown},
1872		{"C:\\", true, Win},
1873		{"c:\\path\\file\\", true, Win},
1874		{"c:/path/file/", false, Unknown},
1875		{"/path/file/", true, Unix},
1876		{"/path/file:SAMPLE/", true, Unix},
1877		{"/path/file:/.txt", true, Unix},
1878		{"/path", true, Unix},
1879		{"/path/__bc/file.txt", true, Unix},
1880		{"/path/a--ac/file.txt", true, Unix},
1881		{"/_path/file.txt", true, Unix},
1882		{"/path/__bc/file.txt", true, Unix},
1883		{"/path/a--ac/file.txt", true, Unix},
1884		{"/__path/--file.txt", true, Unix},
1885		{"/path/a bc", true, Unix},
1886	}
1887	for _, test := range tests {
1888		actual, osType := IsFilePath(test.param)
1889		if actual != test.expected || osType != test.osType {
1890			t.Errorf("Expected IsFilePath(%q) to be %v, got %v", test.param, test.expected, actual)
1891		}
1892	}
1893}
1894
1895func TestIsLatitude(t *testing.T) {
1896	t.Parallel()
1897
1898	var tests = []struct {
1899		param    string
1900		expected bool
1901	}{
1902		{"", false},
1903		{"-90.000", true},
1904		{"+90", true},
1905		{"47.1231231", true},
1906		{"+99.9", false},
1907		{"108", false},
1908	}
1909	for _, test := range tests {
1910		actual := IsLatitude(test.param)
1911		if actual != test.expected {
1912			t.Errorf("Expected IsLatitude(%q) to be %v, got %v", test.param, test.expected, actual)
1913		}
1914	}
1915}
1916
1917func TestIsLongitude(t *testing.T) {
1918	t.Parallel()
1919
1920	var tests = []struct {
1921		param    string
1922		expected bool
1923	}{
1924		{"", false},
1925		{"-180.000", true},
1926		{"180.1", false},
1927		{"+73.234", true},
1928		{"+382.3811", false},
1929		{"23.11111111", true},
1930	}
1931	for _, test := range tests {
1932		actual := IsLongitude(test.param)
1933		if actual != test.expected {
1934			t.Errorf("Expected IsLongitude(%q) to be %v, got %v", test.param, test.expected, actual)
1935		}
1936	}
1937}
1938
1939func TestIsSSN(t *testing.T) {
1940	t.Parallel()
1941
1942	var tests = []struct {
1943		param    string
1944		expected bool
1945	}{
1946		{"", false},
1947		{"00-90-8787", false},
1948		{"66690-76", false},
1949		{"191 60 2869", true},
1950		{"191-60-2869", true},
1951	}
1952	for _, test := range tests {
1953		actual := IsSSN(test.param)
1954		if actual != test.expected {
1955			t.Errorf("Expected IsSSN(%q) to be %v, got %v", test.param, test.expected, actual)
1956		}
1957	}
1958}
1959
1960func TestIsMongoID(t *testing.T) {
1961	t.Parallel()
1962
1963	var tests = []struct {
1964		param    string
1965		expected bool
1966	}{
1967		{"507f1f77bcf86cd799439011", true},
1968		{"507f1f77bcf86cd7994390", false},
1969		{"507f1f77bcf86cd79943901z", false},
1970		{"507f1f77bcf86cd799439011 ", false},
1971		{"", false},
1972	}
1973	for _, test := range tests {
1974		actual := IsMongoID(test.param)
1975		if actual != test.expected {
1976			t.Errorf("Expected IsMongoID(%q) to be %v, got %v", test.param, test.expected, actual)
1977		}
1978	}
1979}
1980
1981func TestIsSemver(t *testing.T) {
1982	t.Parallel()
1983	var tests = []struct {
1984		param    string
1985		expected bool
1986	}{
1987		{"v1.0.0", true},
1988		{"1.0.0", true},
1989		{"1.1.01", false},
1990		{"1.01.0", false},
1991		{"01.1.0", false},
1992		{"v1.1.01", false},
1993		{"v1.01.0", false},
1994		{"v01.1.0", false},
1995		{"1.0.0-alpha", true},
1996		{"1.0.0-alpha.1", true},
1997		{"1.0.0-0.3.7", true},
1998		{"1.0.0-0.03.7", false},
1999		{"1.0.0-00.3.7", false},
2000		{"1.0.0-x.7.z.92", true},
2001		{"1.0.0-alpha+001", true},
2002		{"1.0.0+20130313144700", true},
2003		{"1.0.0-beta+exp.sha.5114f85", true},
2004		{"1.0.0-beta+exp.sha.05114f85", true},
2005		{"1.0.0-+beta", false},
2006		{"1.0.0-b+-9+eta", false},
2007		{"v+1.8.0-b+-9+eta", false},
2008	}
2009	for _, test := range tests {
2010		actual := IsSemver(test.param)
2011		if actual != test.expected {
2012			t.Errorf("Expected IsSemver(%q) to be %v, got %v", test.param, test.expected, actual)
2013		}
2014	}
2015}
2016
2017func TestIsTime(t *testing.T) {
2018	t.Parallel()
2019	var tests = []struct {
2020		param    string
2021		format   string
2022		expected bool
2023	}{
2024		{"2016-12-31 11:00", time.RFC3339, false},
2025		{"2016-12-31 11:00:00", time.RFC3339, false},
2026		{"2016-12-31T11:00", time.RFC3339, false},
2027		{"2016-12-31T11:00:00", time.RFC3339, false},
2028		{"2016-12-31T11:00:00Z", time.RFC3339, true},
2029		{"2016-12-31T11:00:00+01:00", time.RFC3339, true},
2030		{"2016-12-31T11:00:00-01:00", time.RFC3339, true},
2031		{"2016-12-31T11:00:00.05Z", time.RFC3339, true},
2032		{"2016-12-31T11:00:00.05-01:00", time.RFC3339, true},
2033		{"2016-12-31T11:00:00.05+01:00", time.RFC3339, true},
2034		{"2016-12-31T11:00:00", RF3339WithoutZone, true},
2035		{"2016-12-31T11:00:00Z", RF3339WithoutZone, false},
2036		{"2016-12-31T11:00:00+01:00", RF3339WithoutZone, false},
2037		{"2016-12-31T11:00:00-01:00", RF3339WithoutZone, false},
2038		{"2016-12-31T11:00:00.05Z", RF3339WithoutZone, false},
2039		{"2016-12-31T11:00:00.05-01:00", RF3339WithoutZone, false},
2040		{"2016-12-31T11:00:00.05+01:00", RF3339WithoutZone, false},
2041	}
2042	for _, test := range tests {
2043		actual := IsTime(test.param, test.format)
2044		if actual != test.expected {
2045			t.Errorf("Expected IsTime(%q, time.RFC3339) to be %v, got %v", test.param, test.expected, actual)
2046		}
2047	}
2048}
2049
2050func TestIsRFC3339(t *testing.T) {
2051	t.Parallel()
2052	var tests = []struct {
2053		param    string
2054		expected bool
2055	}{
2056		{"2016-12-31 11:00", false},
2057		{"2016-12-31 11:00:00", false},
2058		{"2016-12-31T11:00", false},
2059		{"2016-12-31T11:00:00", false},
2060		{"2016-12-31T11:00:00Z", true},
2061		{"2016-12-31T11:00:00+01:00", true},
2062		{"2016-12-31T11:00:00-01:00", true},
2063		{"2016-12-31T11:00:00.05Z", true},
2064		{"2016-12-31T11:00:00.05-01:00", true},
2065		{"2016-12-31T11:00:00.05+01:00", true},
2066	}
2067	for _, test := range tests {
2068		actual := IsRFC3339(test.param)
2069		if actual != test.expected {
2070			t.Errorf("Expected IsRFC3339(%q) to be %v, got %v", test.param, test.expected, actual)
2071		}
2072	}
2073}
2074
2075func TestIsISO4217(t *testing.T) {
2076	t.Parallel()
2077
2078	var tests = []struct {
2079		param    string
2080		expected bool
2081	}{
2082		{"", false},
2083		{"ABCD", false},
2084		{"A", false},
2085		{"ZZZ", false},
2086		{"usd", false},
2087		{"USD", true},
2088	}
2089	for _, test := range tests {
2090		actual := IsISO4217(test.param)
2091		if actual != test.expected {
2092			t.Errorf("Expected IsISO4217(%q) to be %v, got %v", test.param, test.expected, actual)
2093		}
2094	}
2095}
2096
2097func TestByteLength(t *testing.T) {
2098	t.Parallel()
2099
2100	var tests = []struct {
2101		value    string
2102		min      string
2103		max      string
2104		expected bool
2105	}{
2106		{"123456", "0", "100", true},
2107		{"1239999", "0", "0", false},
2108		{"1239asdfasf99", "100", "200", false},
2109		{"1239999asdff29", "10", "30", true},
2110		{"你", "0", "1", false},
2111	}
2112	for _, test := range tests {
2113		actual := ByteLength(test.value, test.min, test.max)
2114		if actual != test.expected {
2115			t.Errorf("Expected ByteLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual)
2116		}
2117	}
2118}
2119
2120func TestRuneLength(t *testing.T) {
2121	t.Parallel()
2122
2123	var tests = []struct {
2124		value    string
2125		min      string
2126		max      string
2127		expected bool
2128	}{
2129		{"123456", "0", "100", true},
2130		{"1239999", "0", "0", false},
2131		{"1239asdfasf99", "100", "200", false},
2132		{"1239999asdff29", "10", "30", true},
2133		{"你", "0", "1", true},
2134	}
2135	for _, test := range tests {
2136		actual := RuneLength(test.value, test.min, test.max)
2137		if actual != test.expected {
2138			t.Errorf("Expected RuneLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual)
2139		}
2140	}
2141}
2142
2143func TestStringLength(t *testing.T) {
2144	t.Parallel()
2145
2146	var tests = []struct {
2147		value    string
2148		min      string
2149		max      string
2150		expected bool
2151	}{
2152		{"123456", "0", "100", true},
2153		{"1239999", "0", "0", false},
2154		{"1239asdfasf99", "100", "200", false},
2155		{"1239999asdff29", "10", "30", true},
2156		{"あいうえお", "0", "5", true},
2157		{"あいうえおか", "0", "5", false},
2158		{"あいうえお", "0", "0", false},
2159		{"あいうえ", "5", "10", false},
2160	}
2161	for _, test := range tests {
2162		actual := StringLength(test.value, test.min, test.max)
2163		if actual != test.expected {
2164			t.Errorf("Expected StringLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual)
2165		}
2166	}
2167}
2168
2169func TestIsIn(t *testing.T) {
2170	t.Parallel()
2171
2172	var tests = []struct {
2173		value    string
2174		params   []string
2175		expected bool
2176	}{
2177		{"PRESENT", []string{"PRESENT"}, true},
2178		{"PRESENT", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, true},
2179		{"PRÉSENTE", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, true},
2180		{"PRESENT", []string{}, false},
2181		{"PRESENT", nil, false},
2182		{"ABSENT", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, false},
2183		{"", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, false},
2184	}
2185	for _, test := range tests {
2186		actual := IsIn(test.value, test.params...)
2187		if actual != test.expected {
2188			t.Errorf("Expected IsIn(%s, %v) to be %v, got %v", test.value, test.params, test.expected, actual)
2189		}
2190	}
2191}
2192
2193type Address struct {
2194	Street string `valid:"-"`
2195	Zip    string `json:"zip" valid:"numeric,required"`
2196}
2197
2198type User struct {
2199	Name     string `valid:"required"`
2200	Email    string `valid:"required,email"`
2201	Password string `valid:"required"`
2202	Age      int    `valid:"required,numeric,@#\u0000"`
2203	Home     *Address
2204	Work     []Address
2205}
2206
2207type UserValid struct {
2208	Name     string `valid:"required"`
2209	Email    string `valid:"required,email"`
2210	Password string `valid:"required"`
2211	Age      int    `valid:"required"`
2212	Home     *Address
2213	Work     []Address `valid:"required"`
2214}
2215
2216type PrivateStruct struct {
2217	privateField string `valid:"required,alpha,d_k"`
2218	NonZero      int
2219	ListInt      []int
2220	ListString   []string `valid:"alpha"`
2221	Work         [2]Address
2222	Home         Address
2223	Map          map[string]Address
2224}
2225
2226type NegationStruct struct {
2227	NotInt string `valid:"!int"`
2228	Int    string `valid:"int"`
2229}
2230
2231type LengthStruct struct {
2232	Length string `valid:"length(10|20)"`
2233}
2234
2235type StringLengthStruct struct {
2236	Length string `valid:"stringlength(10|20)"`
2237}
2238
2239type StringMatchesStruct struct {
2240	StringMatches string `valid:"matches(^[0-9]{3}$)"`
2241}
2242
2243// TODO: this testcase should be fixed
2244// type StringMatchesComplexStruct struct {
2245// 	StringMatches string `valid:"matches(^\\$\\([\"']\\w+[\"']\\)$)"`
2246// }
2247
2248type IsInStruct struct {
2249	IsIn string `valid:"in(PRESENT|PRÉSENTE|NOTABSENT)"`
2250}
2251
2252type Post struct {
2253	Title    string `valid:"alpha,required"`
2254	Message  string `valid:"ascii"`
2255	AuthorIP string `valid:"ipv4"`
2256}
2257
2258type MissingValidationDeclarationStruct struct {
2259	Name  string ``
2260	Email string `valid:"required,email"`
2261}
2262
2263type FieldRequiredByDefault struct {
2264	Email string `valid:"email"`
2265}
2266
2267type MultipleFieldsRequiredByDefault struct {
2268	Url   string `valid:"url"`
2269	Email string `valid:"email"`
2270}
2271
2272type FieldsRequiredByDefaultButExemptStruct struct {
2273	Name  string `valid:"-"`
2274	Email string `valid:"email"`
2275}
2276
2277type FieldsRequiredByDefaultButExemptOrOptionalStruct struct {
2278	Name  string `valid:"-"`
2279	Email string `valid:"optional,email"`
2280}
2281
2282type MessageWithSeveralFieldsStruct struct {
2283	Title string `valid:"length(1|10)"`
2284	Body  string `valid:"length(1|10)"`
2285}
2286
2287func TestValidateMissingValidationDeclarationStruct(t *testing.T) {
2288	var tests = []struct {
2289		param    MissingValidationDeclarationStruct
2290		expected bool
2291	}{
2292		{MissingValidationDeclarationStruct{}, false},
2293		{MissingValidationDeclarationStruct{Name: "TEST", Email: "test@example.com"}, false},
2294	}
2295	SetFieldsRequiredByDefault(true)
2296	for _, test := range tests {
2297		actual, err := ValidateStruct(test.param)
2298		if actual != test.expected {
2299			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2300			if err != nil {
2301				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2302			}
2303		}
2304	}
2305	SetFieldsRequiredByDefault(false)
2306}
2307
2308func TestFieldRequiredByDefault(t *testing.T) {
2309	var tests = []struct {
2310		param    FieldRequiredByDefault
2311		expected bool
2312	}{
2313		{FieldRequiredByDefault{}, false},
2314	}
2315	SetFieldsRequiredByDefault(true)
2316	for _, test := range tests {
2317		actual, err := ValidateStruct(test.param)
2318		if actual != test.expected {
2319			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2320			if err != nil {
2321				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2322			}
2323		}
2324	}
2325	SetFieldsRequiredByDefault(false)
2326}
2327
2328func TestMultipleFieldsRequiredByDefault(t *testing.T) {
2329	var tests = []struct {
2330		param    MultipleFieldsRequiredByDefault
2331		expected bool
2332	}{
2333		{MultipleFieldsRequiredByDefault{}, false},
2334	}
2335	SetFieldsRequiredByDefault(true)
2336	for _, test := range tests {
2337		actual, err := ValidateStruct(test.param)
2338		if actual != test.expected {
2339			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2340			if err != nil {
2341				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2342			}
2343		}
2344	}
2345	SetFieldsRequiredByDefault(false)
2346}
2347
2348func TestFieldsRequiredByDefaultButExemptStruct(t *testing.T) {
2349	var tests = []struct {
2350		param    FieldsRequiredByDefaultButExemptStruct
2351		expected bool
2352	}{
2353		{FieldsRequiredByDefaultButExemptStruct{}, false},
2354		{FieldsRequiredByDefaultButExemptStruct{Name: "TEST"}, false},
2355		{FieldsRequiredByDefaultButExemptStruct{Email: ""}, false},
2356		{FieldsRequiredByDefaultButExemptStruct{Email: "test@example.com"}, true},
2357	}
2358	SetFieldsRequiredByDefault(true)
2359	for _, test := range tests {
2360		actual, err := ValidateStruct(test.param)
2361		if actual != test.expected {
2362			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2363			if err != nil {
2364				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2365			}
2366		}
2367	}
2368	SetFieldsRequiredByDefault(false)
2369}
2370
2371func TestFieldsRequiredByDefaultButExemptOrOptionalStruct(t *testing.T) {
2372	var tests = []struct {
2373		param    FieldsRequiredByDefaultButExemptOrOptionalStruct
2374		expected bool
2375	}{
2376		{FieldsRequiredByDefaultButExemptOrOptionalStruct{}, true},
2377		{FieldsRequiredByDefaultButExemptOrOptionalStruct{Name: "TEST"}, true},
2378		{FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: ""}, true},
2379		{FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: "test@example.com"}, true},
2380		{FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: "test@example"}, false},
2381	}
2382	SetFieldsRequiredByDefault(true)
2383	for _, test := range tests {
2384		actual, err := ValidateStruct(test.param)
2385		if actual != test.expected {
2386			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2387			if err != nil {
2388				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2389			}
2390		}
2391	}
2392	SetFieldsRequiredByDefault(false)
2393}
2394
2395func TestInvalidValidator(t *testing.T) {
2396	type InvalidStruct struct {
2397		Field int `valid:"someInvalidValidator"`
2398	}
2399
2400	invalidStruct := InvalidStruct{1}
2401	if valid, err := ValidateStruct(&invalidStruct); valid || err == nil ||
2402		err.Error() != `Field: The following validator is invalid or can't be applied to the field: "someInvalidValidator"` {
2403		t.Errorf("Got an unexpected result for struct with invalid validator: %t %s", valid, err)
2404	}
2405}
2406
2407func TestCustomValidator(t *testing.T) {
2408	type ValidStruct struct {
2409		Field int `valid:"customTrueValidator"`
2410	}
2411
2412	type InvalidStruct struct {
2413		Field int `valid:"customFalseValidator~Value: %s Custom validator error: %s"`
2414	}
2415
2416	type StructWithCustomAndBuiltinValidator struct {
2417		Field int `valid:"customTrueValidator,required"`
2418	}
2419
2420	if valid, err := ValidateStruct(&ValidStruct{Field: 1}); !valid || err != nil {
2421		t.Errorf("Got an unexpected result for struct with custom always true validator: %t %s", valid, err)
2422	}
2423
2424	if valid, err := ValidateStruct(&InvalidStruct{Field: 1}); valid || err == nil || err.Error() != "Value: 1 Custom validator error: customFalseValidator" {
2425		fmt.Println(err)
2426		t.Errorf("Got an unexpected result for struct with custom always false validator: %t %s", valid, err)
2427	}
2428
2429	mixedStruct := StructWithCustomAndBuiltinValidator{}
2430	if valid, err := ValidateStruct(&mixedStruct); valid || err == nil || err.Error() != "Field: non zero value required" {
2431		t.Errorf("Got an unexpected result for invalid struct with custom and built-in validators: %t %s", valid, err)
2432	}
2433
2434	mixedStruct.Field = 1
2435	if valid, err := ValidateStruct(&mixedStruct); !valid || err != nil {
2436		t.Errorf("Got an unexpected result for valid struct with custom and built-in validators: %t %s", valid, err)
2437	}
2438}
2439
2440type CustomByteArray [6]byte
2441
2442type StructWithCustomByteArray struct {
2443	ID              CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"`
2444	Email           string          `valid:"email"`
2445	CustomMinLength int             `valid:"-"`
2446}
2447
2448func TestStructWithCustomByteArray(t *testing.T) {
2449	t.Parallel()
2450
2451	// add our custom byte array validator that fails when the byte array is pristine (all zeroes)
2452	CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool {
2453		switch v := o.(type) {
2454		case StructWithCustomByteArray:
2455			if len(v.Email) > 0 {
2456				if v.Email != "test@example.com" {
2457					t.Errorf("v.Email should have been 'test@example.com' but was '%s'", v.Email)
2458				}
2459			}
2460		default:
2461			t.Errorf("Context object passed to custom validator should have been a StructWithCustomByteArray but was %T (%+v)", o, o)
2462		}
2463
2464		switch v := i.(type) {
2465		case CustomByteArray:
2466			for _, e := range v { // check if v is empty, i.e. all zeroes
2467				if e != 0 {
2468					return true
2469				}
2470			}
2471		}
2472		return false
2473	}))
2474	CustomTypeTagMap.Set("customMinLengthValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool {
2475		switch v := o.(type) {
2476		case StructWithCustomByteArray:
2477			return len(v.ID) >= v.CustomMinLength
2478		}
2479		return false
2480	}))
2481	testCustomByteArray := CustomByteArray{'1', '2', '3', '4', '5', '6'}
2482	var tests = []struct {
2483		param    StructWithCustomByteArray
2484		expected bool
2485	}{
2486		{StructWithCustomByteArray{}, false},
2487		{StructWithCustomByteArray{Email: "test@example.com"}, false},
2488		{StructWithCustomByteArray{ID: testCustomByteArray, Email: "test@example.com"}, true},
2489		{StructWithCustomByteArray{ID: testCustomByteArray, Email: "test@example.com", CustomMinLength: 7}, false},
2490	}
2491	SetFieldsRequiredByDefault(true)
2492	for _, test := range tests {
2493		actual, err := ValidateStruct(test.param)
2494		if actual != test.expected {
2495			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2496			if err != nil {
2497				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2498			}
2499		}
2500	}
2501	SetFieldsRequiredByDefault(false)
2502}
2503
2504func TestValidateNegationStruct(t *testing.T) {
2505	var tests = []struct {
2506		param    NegationStruct
2507		expected bool
2508	}{
2509		{NegationStruct{"a1", "11"}, true},
2510		{NegationStruct{"email@email.email", "11"}, true},
2511		{NegationStruct{"123456----", "11"}, true},
2512		{NegationStruct{"::1", "11"}, true},
2513		{NegationStruct{"123.123", "11"}, true},
2514		{NegationStruct{"a1", "a1"}, false},
2515		{NegationStruct{"11", "a1"}, false},
2516		{NegationStruct{"11", "11"}, false},
2517	}
2518	for _, test := range tests {
2519		actual, err := ValidateStruct(test.param)
2520		if actual != test.expected {
2521			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2522			if err != nil {
2523				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2524			}
2525		}
2526	}
2527}
2528
2529func TestLengthStruct(t *testing.T) {
2530	var tests = []struct {
2531		param    interface{}
2532		expected bool
2533	}{
2534		{LengthStruct{"11111"}, false},
2535		{LengthStruct{"11111111111111111110000000000000000"}, false},
2536		{LengthStruct{"11dfffdf0099"}, true},
2537	}
2538
2539	for _, test := range tests {
2540		actual, err := ValidateStruct(test.param)
2541		if actual != test.expected {
2542			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2543			if err != nil {
2544				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2545			}
2546		}
2547	}
2548}
2549
2550func TestStringLengthStruct(t *testing.T) {
2551	var tests = []struct {
2552		param    interface{}
2553		expected bool
2554	}{
2555		{StringLengthStruct{"11111"}, false},
2556		{StringLengthStruct{"11111111111111111110000000000000000"}, false},
2557		{StringLengthStruct{"11dfffdf0099"}, true},
2558		{StringLengthStruct{"あいうえお"}, false},
2559		{StringLengthStruct{"あいうえおかきくけこ"}, true},
2560		{StringLengthStruct{"あいうえおかきくけこさしすせそたちつてと"}, true},
2561		{StringLengthStruct{"あいうえおかきくけこさしすせそたちつてとな"}, false},
2562	}
2563
2564	for _, test := range tests {
2565		actual, err := ValidateStruct(test.param)
2566		if actual != test.expected {
2567			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2568			if err != nil {
2569				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2570			}
2571		}
2572	}
2573}
2574
2575func TestStringMatchesStruct(t *testing.T) {
2576	var tests = []struct {
2577		param    interface{}
2578		expected bool
2579	}{
2580		{StringMatchesStruct{"123"}, true},
2581		{StringMatchesStruct{"123456"}, false},
2582		{StringMatchesStruct{"123abcd"}, false},
2583	}
2584
2585	for _, test := range tests {
2586		actual, err := ValidateStruct(test.param)
2587		if actual != test.expected {
2588			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2589			if err != nil {
2590				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2591			}
2592		}
2593	}
2594}
2595
2596func TestIsInStruct(t *testing.T) {
2597	var tests = []struct {
2598		param    interface{}
2599		expected bool
2600	}{
2601		{IsInStruct{"PRESENT"}, true},
2602		{IsInStruct{""}, true},
2603		{IsInStruct{" "}, false},
2604		{IsInStruct{"ABSENT"}, false},
2605	}
2606
2607	for _, test := range tests {
2608		actual, err := ValidateStruct(test.param)
2609		if actual != test.expected {
2610			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2611			if err != nil {
2612				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2613			}
2614		}
2615	}
2616}
2617
2618func TestRequiredIsInStruct(t *testing.T) {
2619	type RequiredIsInStruct struct {
2620		IsIn string `valid:"in(PRESENT|PRÉSENTE|NOTABSENT),required"`
2621	}
2622
2623	var tests = []struct {
2624		param    interface{}
2625		expected bool
2626	}{
2627		{RequiredIsInStruct{"PRESENT"}, true},
2628		{RequiredIsInStruct{""}, false},
2629		{RequiredIsInStruct{" "}, false},
2630		{RequiredIsInStruct{"ABSENT"}, false},
2631	}
2632
2633	for _, test := range tests {
2634		actual, err := ValidateStruct(test.param)
2635		if actual != test.expected {
2636			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2637			if err != nil {
2638				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2639			}
2640		}
2641	}
2642}
2643
2644func TestEmptyRequiredIsInStruct(t *testing.T) {
2645	type EmptyRequiredIsInStruct struct {
2646		IsIn string `valid:"in(),required"`
2647	}
2648
2649	var tests = []struct {
2650		param    interface{}
2651		expected bool
2652	}{
2653		{EmptyRequiredIsInStruct{"PRESENT"}, false},
2654		{EmptyRequiredIsInStruct{""}, false},
2655		{EmptyRequiredIsInStruct{" "}, false},
2656		{EmptyRequiredIsInStruct{"ABSENT"}, false},
2657	}
2658
2659	for _, test := range tests {
2660		actual, err := ValidateStruct(test.param)
2661		if actual != test.expected {
2662			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2663			if err != nil {
2664				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2665			}
2666		}
2667	}
2668}
2669
2670func TestEmptyStringPtr(t *testing.T) {
2671	type EmptyIsInStruct struct {
2672		IsIn *string `valid:"length(3|5),required"`
2673	}
2674
2675	var empty = ""
2676	var valid = "123"
2677	var invalid = "123456"
2678
2679	var tests = []struct {
2680		param       interface{}
2681		expected    bool
2682		expectedErr string
2683	}{
2684		{EmptyIsInStruct{&empty}, false, "IsIn: non zero value required"},
2685		{EmptyIsInStruct{nil}, true, ""},
2686		{EmptyIsInStruct{&valid}, true, ""},
2687		{EmptyIsInStruct{&invalid}, false, "IsIn: 123456 does not validate as length(3|5)"},
2688	}
2689
2690	SetNilPtrAllowedByRequired(true)
2691	for _, test := range tests {
2692		actual, err := ValidateStruct(test.param)
2693
2694		if actual != test.expected {
2695			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2696		}
2697		if err != nil {
2698			if err.Error() != test.expectedErr {
2699				t.Errorf("Got Error on ValidateStruct(%q). Expected: %s Actual: %s", test.param, test.expectedErr, err)
2700			}
2701		} else if test.expectedErr != "" {
2702			t.Errorf("Expected error on ValidateStruct(%q).", test.param)
2703		}
2704	}
2705	SetNilPtrAllowedByRequired(false)
2706}
2707
2708func TestNestedStruct(t *testing.T) {
2709	type EvenMoreNestedStruct struct {
2710		Bar string `valid:"length(3|5)"`
2711	}
2712	type NestedStruct struct {
2713		Foo                 string `valid:"length(3|5),required"`
2714		EvenMoreNested      EvenMoreNestedStruct
2715		SliceEvenMoreNested []EvenMoreNestedStruct
2716		MapEvenMoreNested   map[string]EvenMoreNestedStruct
2717	}
2718	type OuterStruct struct {
2719		Nested NestedStruct
2720	}
2721
2722	var tests = []struct {
2723		param       interface{}
2724		expected    bool
2725		expectedErr string
2726	}{
2727		{OuterStruct{
2728			Nested: NestedStruct{
2729				Foo: "",
2730			},
2731		}, false, "Nested.Foo: non zero value required"},
2732		{OuterStruct{
2733			Nested: NestedStruct{
2734				Foo: "123",
2735			},
2736		}, true, ""},
2737		{OuterStruct{
2738			Nested: NestedStruct{
2739				Foo: "123456",
2740			},
2741		}, false, "Nested.Foo: 123456 does not validate as length(3|5)"},
2742		{OuterStruct{
2743			Nested: NestedStruct{
2744				Foo: "123",
2745				EvenMoreNested: EvenMoreNestedStruct{
2746					Bar: "123456",
2747				},
2748			},
2749		}, false, "Nested.EvenMoreNested.Bar: 123456 does not validate as length(3|5)"},
2750		{OuterStruct{
2751			Nested: NestedStruct{
2752				Foo: "123",
2753				SliceEvenMoreNested: []EvenMoreNestedStruct{
2754					EvenMoreNestedStruct{
2755						Bar: "123456",
2756					},
2757				},
2758			},
2759		}, false, "Nested.SliceEvenMoreNested.0.Bar: 123456 does not validate as length(3|5)"},
2760		{OuterStruct{
2761			Nested: NestedStruct{
2762				Foo: "123",
2763				MapEvenMoreNested: map[string]EvenMoreNestedStruct{
2764					"Foo": EvenMoreNestedStruct{
2765						Bar: "123456",
2766					},
2767				},
2768			},
2769		}, false, "Nested.MapEvenMoreNested.Foo.Bar: 123456 does not validate as length(3|5)"},
2770	}
2771
2772	for _, test := range tests {
2773		actual, err := ValidateStruct(test.param)
2774
2775		if actual != test.expected {
2776			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2777		}
2778		if err != nil {
2779			if err.Error() != test.expectedErr {
2780				t.Errorf("Got Error on ValidateStruct(%q). Expected: %s Actual: %s", test.param, test.expectedErr, err)
2781			}
2782		} else if test.expectedErr != "" {
2783			t.Errorf("Expected error on ValidateStruct(%q).", test.param)
2784		}
2785	}
2786}
2787
2788func TestFunkyIsInStruct(t *testing.T) {
2789	type FunkyIsInStruct struct {
2790		IsIn string `valid:"in(PRESENT|| |PRÉSENTE|NOTABSENT)"`
2791	}
2792
2793	var tests = []struct {
2794		param    interface{}
2795		expected bool
2796	}{
2797		{FunkyIsInStruct{"PRESENT"}, true},
2798		{FunkyIsInStruct{""}, true},
2799		{FunkyIsInStruct{" "}, true},
2800		{FunkyIsInStruct{"ABSENT"}, false},
2801	}
2802
2803	for _, test := range tests {
2804		actual, err := ValidateStruct(test.param)
2805		if actual != test.expected {
2806			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2807			if err != nil {
2808				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2809			}
2810		}
2811	}
2812}
2813
2814// TODO: test case broken
2815// func TestStringMatchesComplexStruct(t *testing.T) {
2816// 	var tests = []struct {
2817// 		param    interface{}
2818// 		expected bool
2819// 	}{
2820// 		{StringMatchesComplexStruct{"$()"}, false},
2821// 		{StringMatchesComplexStruct{"$('AZERTY')"}, true},
2822// 		{StringMatchesComplexStruct{`$("AZERTY")`}, true},
2823// 		{StringMatchesComplexStruct{`$("")`}, false},
2824// 		{StringMatchesComplexStruct{"AZERTY"}, false},
2825// 		{StringMatchesComplexStruct{"$AZERTY"}, false},
2826// 	}
2827
2828// 	for _, test := range tests {
2829// 		actual, err := ValidateStruct(test.param)
2830// 		if actual != test.expected {
2831// 			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2832// 			if err != nil {
2833// 				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2834// 			}
2835// 		}
2836// 	}
2837// }
2838
2839func TestValidateStruct(t *testing.T) {
2840
2841	var tests = []struct {
2842		param    interface{}
2843		expected bool
2844	}{
2845		{User{"John", "john@yahoo.com", "123G#678", 20, &Address{"Street", "ABC456D89"},    []Address{{"Street", "123456"}, {"Street", "123456"}}}, false},
2846		{User{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false},
2847		{User{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false},
2848		{UserValid{"John", "john@yahoo.com", "123G#678", 20, &Address{"Street", "123456"}, []Address{{"Street", "123456"}, {"Street", "123456"}}}, true},
2849		{UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{}}, false},
2850		{UserValid{"John", "john@yahoo.com", "12345678", 20, &Address{"Street", "123456xxx"}, []Address{{"Street", "123456"}, {"Street", "123456"}}}, false},
2851		{UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false},
2852		{UserValid{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false},
2853		{nil, true},
2854		{User{"John", "john@yahoo.com", "123G#678", 0, &Address{"Street", "123456"}, []Address{}}, false},
2855		{"im not a struct", false},
2856	}
2857	for _, test := range tests {
2858		actual, err := ValidateStruct(test.param)
2859		if actual != test.expected {
2860			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2861			if err != nil {
2862				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
2863			}
2864		}
2865	}
2866
2867	TagMap["d_k"] = Validator(func(str string) bool {
2868		return str == "d_k"
2869	})
2870	result, err := ValidateStruct(PrivateStruct{"d_k", 0, []int{1, 2}, []string{"hi", "super"}, [2]Address{{"Street", "123456"},
2871		{"Street", "123456"}}, Address{"Street", "123456"}, map[string]Address{"address": {"Street", "123456"}}})
2872	if !result {
2873		t.Log("Case ", 6, ": expected ", true, " when result is ", result)
2874		t.Error(err)
2875		t.FailNow()
2876	}
2877}
2878
2879type testByteArray [8]byte
2880type testByteMap map[byte]byte
2881type testByteSlice []byte
2882type testStringStringMap map[string]string
2883type testStringIntMap map[string]int
2884
2885func TestRequired(t *testing.T) {
2886
2887	testString := "foobar"
2888	testEmptyString := ""
2889	var tests = []struct {
2890		param    interface{}
2891		expected bool
2892	}{
2893		{
2894			struct {
2895				Pointer *string `valid:"required"`
2896			}{},
2897			false,
2898		},
2899		{
2900			struct {
2901				Pointer *string `valid:"required"`
2902			}{
2903				Pointer: &testEmptyString,
2904			},
2905			false,
2906		},
2907		{
2908			struct {
2909				Pointer *string `valid:"required"`
2910			}{
2911				Pointer: &testString,
2912			},
2913			true,
2914		},
2915		{
2916			struct {
2917				Addr Address `valid:"required"`
2918			}{},
2919			false,
2920		},
2921		{
2922			struct {
2923				Addr Address `valid:"required"`
2924			}{
2925				Addr: Address{"", "123"},
2926			},
2927			true,
2928		},
2929		{
2930			struct {
2931				Pointer *Address `valid:"required"`
2932			}{},
2933			false,
2934		},
2935		{
2936			struct {
2937				Pointer *Address `valid:"required"`
2938			}{
2939				Pointer: &Address{"", "123"},
2940			},
2941			true,
2942		},
2943		{
2944			struct {
2945				TestByteArray testByteArray `valid:"required"`
2946			}{},
2947			false,
2948		},
2949		{
2950			struct {
2951				TestByteArray testByteArray `valid:"required"`
2952			}{
2953				testByteArray{},
2954			},
2955			false,
2956		},
2957		{
2958			struct {
2959				TestByteArray testByteArray `valid:"required"`
2960			}{
2961				testByteArray{'1', '2', '3', '4', '5', '6', '7', 'A'},
2962			},
2963			true,
2964		},
2965		{
2966			struct {
2967				TestByteMap testByteMap `valid:"required"`
2968			}{},
2969			false,
2970		},
2971		{
2972			struct {
2973				TestByteSlice testByteSlice `valid:"required"`
2974			}{},
2975			false,
2976		},
2977		{
2978			struct {
2979				TestStringStringMap testStringStringMap `valid:"required"`
2980			}{
2981				testStringStringMap{"test": "test"},
2982			},
2983			true,
2984		},
2985		{
2986			struct {
2987				TestIntMap testStringIntMap `valid:"required"`
2988			}{
2989				testStringIntMap{"test": 42},
2990			},
2991			true,
2992		},
2993	}
2994	for _, test := range tests {
2995		actual, err := ValidateStruct(test.param)
2996		if actual != test.expected {
2997			t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual)
2998			if err != nil {
2999				t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err)
3000			}
3001		}
3002	}
3003}
3004
3005func TestErrorByField(t *testing.T) {
3006	t.Parallel()
3007
3008	var tests = []struct {
3009		param    string
3010		expected string
3011	}{
3012		{"message", ""},
3013		{"Message", ""},
3014		{"title", ""},
3015		{"Title", "My123 does not validate as alpha"},
3016		{"AuthorIP", "123 does not validate as ipv4"},
3017	}
3018	post := &Post{"My123", "duck13126", "123"}
3019	_, err := ValidateStruct(post)
3020
3021	for _, test := range tests {
3022		actual := ErrorByField(err, test.param)
3023		if actual != test.expected {
3024			t.Errorf("Expected ErrorByField(%q) to be %v, got %v", test.param, test.expected, actual)
3025		}
3026	}
3027}
3028
3029func TestErrorsByField(t *testing.T) {
3030	t.Parallel()
3031
3032	var tests = []struct {
3033		param    string
3034		expected string
3035	}{
3036		{"Title", "My123 does not validate as alpha"},
3037		{"AuthorIP", "123 does not validate as ipv4"},
3038	}
3039	post := &Post{Title: "My123", Message: "duck13126", AuthorIP: "123"}
3040	_, err := ValidateStruct(post)
3041	errs := ErrorsByField(err)
3042	if len(errs) != 2 {
3043		t.Errorf("There should only be 2 errors but got %v", len(errs))
3044	}
3045
3046	for _, test := range tests {
3047		if actual, ok := errs[test.param]; !ok || actual != test.expected {
3048			t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual)
3049		}
3050	}
3051
3052	tests = []struct {
3053		param    string
3054		expected string
3055	}{
3056		{"Title", ";:;message;:; does not validate as length(1|10)"},
3057		{"Body", ";:;message;:; does not validate as length(1|10)"},
3058	}
3059
3060	message := &MessageWithSeveralFieldsStruct{Title: ";:;message;:;", Body: ";:;message;:;"}
3061	_, err = ValidateStruct(message)
3062	errs = ErrorsByField(err)
3063	if len(errs) != 2 {
3064		t.Errorf("There should only be 2 errors but got %v", len(errs))
3065	}
3066
3067	for _, test := range tests {
3068		if actual, ok := errs[test.param]; !ok || actual != test.expected {
3069			t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual)
3070		}
3071	}
3072
3073	tests = []struct {
3074		param    string
3075		expected string
3076	}{
3077		{"CustomField", "An error occurred"},
3078	}
3079
3080	err = Error{"CustomField", fmt.Errorf("An error occurred"), false, "hello", []string{}}
3081	errs = ErrorsByField(err)
3082
3083	if len(errs) != 1 {
3084		t.Errorf("There should only be 1 errors but got %v", len(errs))
3085	}
3086
3087	for _, test := range tests {
3088		if actual, ok := errs[test.param]; !ok || actual != test.expected {
3089			t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual)
3090		}
3091	}
3092
3093	type StructWithCustomValidation struct {
3094		Email string `valid:"email"`
3095		ID    string `valid:"falseValidation"`
3096	}
3097
3098	CustomTypeTagMap.Set("falseValidation", CustomTypeValidator(func(i interface{}, o interface{}) bool {
3099		return false
3100	}))
3101
3102	tests = []struct {
3103		param    string
3104		expected string
3105	}{
3106		{"Email", "My123 does not validate as email"},
3107		{"ID", "duck13126 does not validate as falseValidation"},
3108	}
3109	s := &StructWithCustomValidation{Email: "My123", ID: "duck13126"}
3110	_, err = ValidateStruct(s)
3111	errs = ErrorsByField(err)
3112	if len(errs) != 2 {
3113		t.Errorf("There should only be 2 errors but got %v", len(errs))
3114	}
3115
3116	for _, test := range tests {
3117		if actual, ok := errs[test.param]; !ok || actual != test.expected {
3118			t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual)
3119		}
3120	}
3121}
3122
3123func TestValidateStructPointers(t *testing.T) {
3124	// Struct which uses pointers for values
3125	type UserWithPointers struct {
3126		Name         *string `valid:"-"`
3127		Email        *string `valid:"email"`
3128		FavoriteFood *string `valid:"length(0|32)"`
3129		Nerd         *bool   `valid:"-"`
3130	}
3131
3132	var tests = []struct {
3133		param    string
3134		expected string
3135	}{
3136		{"Name", ""},
3137		{"Email", "invalid does not validate as email"},
3138		{"FavoriteFood", ""},
3139		{"Nerd", ""},
3140	}
3141
3142	name := "Herman"
3143	email := "invalid"
3144	food := "Pizza"
3145	nerd := true
3146	user := &UserWithPointers{&name, &email, &food, &nerd}
3147	_, err := ValidateStruct(user)
3148
3149	for _, test := range tests {
3150		actual := ErrorByField(err, test.param)
3151		if actual != test.expected {
3152			t.Errorf("Expected ErrorByField(%q) to be %v, got %v", test.param, test.expected, actual)
3153		}
3154	}
3155}
3156
3157func ExampleValidateStruct() {
3158	type Post struct {
3159		Title    string `valid:"alphanum,required"`
3160		Message  string `valid:"duck,ascii"`
3161		AuthorIP string `valid:"ipv4"`
3162	}
3163	post := &Post{"My Example Post", "duck", "123.234.54.3"}
3164
3165	//Add your own struct validation tags
3166	TagMap["duck"] = Validator(func(str string) bool {
3167		return str == "duck"
3168	})
3169
3170	result, err := ValidateStruct(post)
3171	if err != nil {
3172		println("error: " + err.Error())
3173	}
3174	println(result)
3175}
3176
3177func TestValidateStructParamValidatorInt(t *testing.T) {
3178	type Test1 struct {
3179		Int   int   `valid:"range(1|10)"`
3180		Int8  int8  `valid:"range(1|10)"`
3181		Int16 int16 `valid:"range(1|10)"`
3182		Int32 int32 `valid:"range(1|10)"`
3183		Int64 int64 `valid:"range(1|10)"`
3184
3185		Uint   uint   `valid:"range(1|10)"`
3186		Uint8  uint8  `valid:"range(1|10)"`
3187		Uint16 uint16 `valid:"range(1|10)"`
3188		Uint32 uint32 `valid:"range(1|10)"`
3189		Uint64 uint64 `valid:"range(1|10)"`
3190
3191		Float32 float32 `valid:"range(1|10)"`
3192		Float64 float64 `valid:"range(1|10)"`
3193	}
3194	test1Ok := &Test1{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}
3195	test1NotOk := &Test1{11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}
3196
3197	_, err := ValidateStruct(test1Ok)
3198	if err != nil {
3199		t.Errorf("Test failed: %s", err)
3200	}
3201
3202	_, err = ValidateStruct(test1NotOk)
3203	if err == nil {
3204		t.Errorf("Test failed: nil")
3205	}
3206
3207	type Test2 struct {
3208		Int   int   `valid:"in(1|10)"`
3209		Int8  int8  `valid:"in(1|10)"`
3210		Int16 int16 `valid:"in(1|10)"`
3211		Int32 int32 `valid:"in(1|10)"`
3212		Int64 int64 `valid:"in(1|10)"`
3213
3214		Uint   uint   `valid:"in(1|10)"`
3215		Uint8  uint8  `valid:"in(1|10)"`
3216		Uint16 uint16 `valid:"in(1|10)"`
3217		Uint32 uint32 `valid:"in(1|10)"`
3218		Uint64 uint64 `valid:"in(1|10)"`
3219
3220		Float32 float32 `valid:"in(1|10)"`
3221		Float64 float64 `valid:"in(1|10)"`
3222	}
3223
3224	test2Ok1 := &Test2{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
3225	test2Ok2 := &Test2{10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}
3226	test2NotOk := &Test2{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
3227
3228	_, err = ValidateStruct(test2Ok1)
3229	if err != nil {
3230		t.Errorf("Test failed: %s", err)
3231	}
3232
3233	_, err = ValidateStruct(test2Ok2)
3234	if err != nil {
3235		t.Errorf("Test failed: %s", err)
3236	}
3237
3238	_, err = ValidateStruct(test2NotOk)
3239	if err == nil {
3240		t.Errorf("Test failed: nil")
3241	}
3242
3243	type Test3 struct {
3244        Int   int   `valid:"in(1|10),int"`
3245        Int8  int8  `valid:"in(1|10),int8"`
3246        Int16 int16 `valid:"in(1|10),int16"`
3247        Int32 int32 `valid:"in(1|10),int32"`
3248        Int64 int64 `valid:"in(1|10),int64"`
3249
3250        Uint   uint   `valid:"in(1|10),uint"`
3251        Uint8  uint8  `valid:"in(1|10),uint8"`
3252        Uint16 uint16 `valid:"in(1|10),uint16"`
3253        Uint32 uint32 `valid:"in(1|10),uint32"`
3254        Uint64 uint64 `valid:"in(1|10),uint64"`
3255
3256        Float32 float32 `valid:"in(1|10),float32"`
3257        Float64 float64 `valid:"in(1|10),float64"`
3258    }
3259
3260    test3Ok1 := &Test2{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
3261    test3Ok2 := &Test2{10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}
3262    test3NotOk := &Test2{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
3263
3264    _, err = ValidateStruct(test3Ok1)
3265    if err != nil {
3266        t.Errorf("Test failed: %s", err)
3267    }
3268
3269    _, err = ValidateStruct(test3Ok2)
3270    if err != nil {
3271        t.Errorf("Test failed: %s", err)
3272    }
3273
3274    _, err = ValidateStruct(test3NotOk)
3275    if err == nil {
3276        t.Errorf("Test failed: nil")
3277    }
3278}
3279
3280func TestValidateStructUpperAndLowerCaseWithNumTypeCheck(t *testing.T) {
3281
3282    type StructCapital struct {
3283        Total float32 `valid:"float,required"`
3284    }
3285
3286    structCapital := &StructCapital{53.3535}
3287    _, err := ValidateStruct(structCapital)
3288    if err != nil {
3289        t.Errorf("Test failed: nil")
3290        fmt.Println(err)
3291    }
3292
3293    type StructLower struct {
3294        total float32 `valid:"float,required"`
3295    }
3296
3297    structLower := &StructLower{53.3535}
3298    _, err = ValidateStruct(structLower)
3299    if err != nil {
3300        t.Errorf("Test failed: nil")
3301        fmt.Println(err)
3302    }
3303}
3304
3305func TestIsCIDR(t *testing.T) {
3306	t.Parallel()
3307
3308	var tests = []struct {
3309		param    string
3310		expected bool
3311	}{
3312		{"193.168.3.20/7", true},
3313		{"2001:db8::/32", true},
3314		{"2001:0db8:85a3:0000:0000:8a2e:0370:7334/64", true},
3315		{"193.138.3.20/60", false},
3316		{"500.323.2.23/43", false},
3317		{"", false},
3318	}
3319	for _, test := range tests {
3320		actual := IsCIDR(test.param)
3321		if actual != test.expected {
3322			t.Errorf("Expected IsCIDR(%q) to be %v, got %v", test.param, test.expected, actual)
3323		}
3324	}
3325}
3326
3327func TestOptionalCustomValidators(t *testing.T) {
3328
3329	CustomTypeTagMap.Set("f2", CustomTypeValidator(func(i interface{}, o interface{}) bool {
3330		return false
3331	}))
3332
3333	var val struct {
3334		WithCustomError    string `valid:"f2~boom,optional"`
3335		WithoutCustomError string `valid:"f2,optional"`
3336		OptionalFirst      string `valid:"optional,f2"`
3337	}
3338
3339	ok, err := ValidateStruct(val)
3340
3341	if err != nil {
3342		t.Errorf("Expected nil err with optional validation, got %v", err)
3343	}
3344
3345	if !ok {
3346		t.Error("Expected validation to return true, got false")
3347	}
3348}
3349
3350func TestJSONValidator(t *testing.T) {
3351
3352	var val struct {
3353		WithJSONName      string `json:"with_json_name" valid:"-,required"`
3354		WithoutJSONName   string `valid:"-,required"`
3355		WithJSONOmit      string `json:"with_other_json_name,omitempty" valid:"-,required"`
3356		WithJSONOption    string `json:",omitempty" valid:"-,required"`
3357		WithEmptyJSONName string `json:"-" valid:"-,required"`
3358	}
3359
3360	_, err := ValidateStruct(val)
3361
3362	if err == nil {
3363		t.Error("Expected error but got no error")
3364	}
3365
3366	if Contains(err.Error(), "WithJSONName") {
3367		t.Errorf("Expected error message to contain with_json_name but actual error is: %s", err.Error())
3368	}
3369
3370	if !Contains(err.Error(), "WithoutJSONName") {
3371		t.Errorf("Expected error message to contain WithoutJSONName but actual error is: %s", err.Error())
3372	}
3373
3374	if Contains(err.Error(), "omitempty") {
3375		t.Errorf("Expected error message to not contain ',omitempty' but actual error is: %s", err.Error())
3376	}
3377
3378	if !Contains(err.Error(), "WithEmptyJSONName") {
3379		t.Errorf("Expected error message to contain WithEmptyJSONName but actual error is: %s", err.Error())
3380	}
3381}
3382
3383func TestValidatorIncludedInError(t *testing.T) {
3384	post := Post{
3385		Title:    "",
3386		Message:  "��",
3387		AuthorIP: "xyz",
3388	}
3389
3390	validatorMap := map[string]string{
3391		"Title":    "required",
3392		"Message":  "ascii",
3393		"AuthorIP": "ipv4",
3394	}
3395
3396	ok, errors := ValidateStruct(post)
3397	if ok {
3398		t.Errorf("expected validation to fail %v", ok)
3399	}
3400
3401	for _, e := range errors.(Errors) {
3402		casted := e.(Error)
3403		if validatorMap[casted.Name] != casted.Validator {
3404			t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator)
3405		}
3406	}
3407
3408	// check to make sure that validators with arguments (like length(1|10)) don't include the arguments
3409	// in the validator name
3410	message := MessageWithSeveralFieldsStruct{
3411		Title: "",
3412		Body:  "asdfasdfasdfasdfasdf",
3413	}
3414
3415	validatorMap = map[string]string{
3416		"Title": "length",
3417		"Body":  "length",
3418	}
3419
3420	ok, errors = ValidateStruct(message)
3421	if ok {
3422		t.Errorf("expected validation to fail, %v", ok)
3423	}
3424
3425	for _, e := range errors.(Errors) {
3426		casted := e.(Error)
3427		if validatorMap[casted.Name] != casted.Validator {
3428			t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator)
3429		}
3430	}
3431
3432	// make sure validators with custom messages don't show up in the validator string
3433	type CustomMessage struct {
3434		Text string `valid:"length(1|10)~Custom message"`
3435	}
3436	cs := CustomMessage{Text: "asdfasdfasdfasdf"}
3437
3438	ok, errors = ValidateStruct(&cs)
3439	if ok {
3440		t.Errorf("expected validation to fail, %v", ok)
3441	}
3442
3443	validator := errors.(Errors)[0].(Error).Validator
3444	if validator != "length" {
3445		t.Errorf("expected validator for Text to be length, but was %s", validator)
3446	}
3447
3448}
3449
3450func TestIsRsaPublicKey(t *testing.T) {
3451	var tests = []struct {
3452		rsastr   string
3453		keylen   int
3454		expected bool
3455	}{
3456		{`fubar`, 2048, false},
3457		{`MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuu
3458XwKYLq0DKUE3t/HHsNdowfD9+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9BmMEcI3uoKbeXCbJRI
3459HoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzTUmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZ
3460B7ucimFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUvbQIDAQAB`, 2048, true},
3461		{`MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuu
3462XwKYLq0DKUE3t/HHsNdowfD9+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9BmMEcI3uoKbeXCbJRI
3463HoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzTUmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZ
3464B7ucimFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUvbQIDAQAB`, 1024, false},
3465		{`-----BEGIN PUBLIC KEY-----
3466MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7
3467x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuuXwKYLq0DKUE3t/HHsNdowfD9
3468+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9
3469BmMEcI3uoKbeXCbJRIHoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzT
3470UmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZB7uc
3471imFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUv
3472bQIDAQAB
3473-----END PUBLIC KEY-----`, 2048, true},
3474		{`-----BEGIN PUBLIC KEY-----
3475MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7
3476x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuuXwKYLq0DKUE3t/HHsNdowfD9
3477+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9
3478BmMEcI3uoKbeXCbJRIHoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzT
3479UmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZB7uc
3480imFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUv
3481bQIDAQAB
3482-----END PUBLIC KEY-----`, 4096, false},
3483	}
3484	for i, test := range tests {
3485		actual := IsRsaPublicKey(test.rsastr, test.keylen)
3486		if actual != test.expected {
3487			t.Errorf("Expected TestIsRsaPublicKey(%d, %d) to be %v, got %v", i, test.keylen, test.expected, actual)
3488		}
3489	}
3490}
3491