package govalidator import ( "fmt" "strings" "testing" "time" ) func init() { CustomTypeTagMap.Set("customFalseValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { return false })) CustomTypeTagMap.Set("customTrueValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { return true })) } func TestIsAlpha(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"\n", false}, {"\r", false}, {"Ⅸ", false}, {"", true}, {" fooo ", false}, {"abc!!!", false}, {"abc1", false}, {"abc〩", false}, {"abc", true}, {"소주", false}, {"ABC", true}, {"FoObAr", true}, {"소aBC", false}, {"소", false}, {"달기&Co.", false}, {"〩Hours", false}, {"\ufff0", false}, {"\u0070", true}, //UTF-8(ASCII): p {"\u0026", false}, //UTF-8(ASCII): & {"\u0030", false}, //UTF-8(ASCII): 0 {"123", false}, {"0123", false}, {"-00123", false}, {"0", false}, {"-0", false}, {"123.123", false}, {" ", false}, {".", false}, {"-1¾", false}, {"1¾", false}, {"〥〩", false}, {"모자", false}, {"ix", true}, {"۳۵۶۰", false}, {"1--", false}, {"1-1", false}, {"-", false}, {"--", false}, {"1++", false}, {"1+1", false}, {"+", false}, {"++", false}, {"+1", false}, } for _, test := range tests { actual := IsAlpha(test.param) if actual != test.expected { t.Errorf("Expected IsAlpha(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsUTFLetter(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"\n", false}, {"\r", false}, {"Ⅸ", false}, {"", true}, {" fooo ", false}, {"abc!!!", false}, {"abc1", false}, {"abc〩", false}, {"", true}, {"abc", true}, {"소주", true}, {"ABC", true}, {"FoObAr", true}, {"소aBC", true}, {"소", true}, {"달기&Co.", false}, {"〩Hours", false}, {"\ufff0", false}, {"\u0070", true}, //UTF-8(ASCII): p {"\u0026", false}, //UTF-8(ASCII): & {"\u0030", false}, //UTF-8(ASCII): 0 {"123", false}, {"0123", false}, {"-00123", false}, {"0", false}, {"-0", false}, {"123.123", false}, {" ", false}, {".", false}, {"-1¾", false}, {"1¾", false}, {"〥〩", false}, {"모자", true}, {"ix", true}, {"۳۵۶۰", false}, {"1--", false}, {"1-1", false}, {"-", false}, {"--", false}, {"1++", false}, {"1+1", false}, {"+", false}, {"++", false}, {"+1", false}, } for _, test := range tests { actual := IsUTFLetter(test.param) if actual != test.expected { t.Errorf("Expected IsUTFLetter(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsAlphanumeric(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"\n", false}, {"\r", false}, {"Ⅸ", false}, {"", true}, {" fooo ", false}, {"abc!!!", false}, {"abc123", true}, {"ABC111", true}, {"abc1", true}, {"abc〩", false}, {"abc", true}, {"소주", false}, {"ABC", true}, {"FoObAr", true}, {"소aBC", false}, {"소", false}, {"달기&Co.", false}, {"〩Hours", false}, {"\ufff0", false}, {"\u0070", true}, //UTF-8(ASCII): p {"\u0026", false}, //UTF-8(ASCII): & {"\u0030", true}, //UTF-8(ASCII): 0 {"123", true}, {"0123", true}, {"-00123", false}, {"0", true}, {"-0", false}, {"123.123", false}, {" ", false}, {".", false}, {"-1¾", false}, {"1¾", false}, {"〥〩", false}, {"모자", false}, {"ix", true}, {"۳۵۶۰", false}, {"1--", false}, {"1-1", false}, {"-", false}, {"--", false}, {"1++", false}, {"1+1", false}, {"+", false}, {"++", false}, {"+1", false}, } for _, test := range tests { actual := IsAlphanumeric(test.param) if actual != test.expected { t.Errorf("Expected IsAlphanumeric(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsUTFLetterNumeric(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"\n", false}, {"\r", false}, {"Ⅸ", true}, {"", true}, {" fooo ", false}, {"abc!!!", false}, {"abc1", true}, {"abc〩", true}, {"abc", true}, {"소주", true}, {"ABC", true}, {"FoObAr", true}, {"소aBC", true}, {"소", true}, {"달기&Co.", false}, {"〩Hours", true}, {"\ufff0", false}, {"\u0070", true}, //UTF-8(ASCII): p {"\u0026", false}, //UTF-8(ASCII): & {"\u0030", true}, //UTF-8(ASCII): 0 {"123", true}, {"0123", true}, {"-00123", false}, {"0", true}, {"-0", false}, {"123.123", false}, {" ", false}, {".", false}, {"-1¾", false}, {"1¾", true}, {"〥〩", true}, {"모자", true}, {"ix", true}, {"۳۵۶۰", true}, {"1--", false}, {"1-1", false}, {"-", false}, {"--", false}, {"1++", false}, {"1+1", false}, {"+", false}, {"++", false}, {"+1", false}, } for _, test := range tests { actual := IsUTFLetterNumeric(test.param) if actual != test.expected { t.Errorf("Expected IsUTFLetterNumeric(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsNumeric(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"\n", false}, {"\r", false}, {"Ⅸ", false}, {"", true}, {" fooo ", false}, {"abc!!!", false}, {"abc1", false}, {"abc〩", false}, {"abc", false}, {"소주", false}, {"ABC", false}, {"FoObAr", false}, {"소aBC", false}, {"소", false}, {"달기&Co.", false}, {"〩Hours", false}, {"\ufff0", false}, {"\u0070", false}, //UTF-8(ASCII): p {"\u0026", false}, //UTF-8(ASCII): & {"\u0030", true}, //UTF-8(ASCII): 0 {"123", true}, {"0123", true}, {"-00123", false}, {"+00123", false}, {"0", true}, {"-0", false}, {"123.123", false}, {" ", false}, {".", false}, {"12𐅪3", false}, {"-1¾", false}, {"1¾", false}, {"〥〩", false}, {"모자", false}, {"ix", false}, {"۳۵۶۰", false}, {"1--", false}, {"1-1", false}, {"-", false}, {"--", false}, {"1++", false}, {"1+1", false}, {"+", false}, {"++", false}, {"+1", false}, } for _, test := range tests { actual := IsNumeric(test.param) if actual != test.expected { t.Errorf("Expected IsNumeric(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsUTFNumeric(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"\n", false}, {"\r", false}, {"Ⅸ", true}, {"", true}, {" fooo ", false}, {"abc!!!", false}, {"abc1", false}, {"abc〩", false}, {"abc", false}, {"소주", false}, {"ABC", false}, {"FoObAr", false}, {"소aBC", false}, {"소", false}, {"달기&Co.", false}, {"〩Hours", false}, {"\ufff0", false}, {"\u0070", false}, //UTF-8(ASCII): p {"\u0026", false}, //UTF-8(ASCII): & {"\u0030", true}, //UTF-8(ASCII): 0 {"123", true}, {"0123", true}, {"-00123", true}, {"0", true}, {"-0", true}, {"--0", false}, {"-0-", false}, {"123.123", false}, {" ", false}, {".", false}, {"12𐅪3", true}, {"-1¾", true}, {"1¾", true}, {"〥〩", true}, {"모자", false}, {"ix", false}, {"۳۵۶۰", true}, {"1++", false}, {"1+1", false}, {"+", false}, {"++", false}, {"+1", true}, } for _, test := range tests { actual := IsUTFNumeric(test.param) if actual != test.expected { t.Errorf("Expected IsUTFNumeric(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsUTFDigit(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"\n", false}, {"\r", false}, {"Ⅸ", false}, {"", true}, {" fooo ", false}, {"abc!!!", false}, {"abc1", false}, {"abc〩", false}, {"abc", false}, {"소주", false}, {"ABC", false}, {"FoObAr", false}, {"소aBC", false}, {"소", false}, {"달기&Co.", false}, {"〩Hours", false}, {"\ufff0", false}, {"\u0070", false}, //UTF-8(ASCII): p {"\u0026", false}, //UTF-8(ASCII): & {"\u0030", true}, //UTF-8(ASCII): 0 {"123", true}, {"0123", true}, {"-00123", true}, {"0", true}, {"-0", true}, {"--0", false}, {"-0-", false}, {"123.123", false}, {" ", false}, {".", false}, {"12𐅪3", false}, {"1483920", true}, {"", true}, {"۳۵۶۰", true}, {"-29", true}, {"-1¾", false}, {"1¾", false}, {"〥〩", false}, {"모자", false}, {"ix", false}, {"۳۵۶۰", true}, {"1++", false}, {"1+1", false}, {"+", false}, {"++", false}, {"+1", true}, } for _, test := range tests { actual := IsUTFDigit(test.param) if actual != test.expected { t.Errorf("Expected IsUTFDigit(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsLowerCase(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", true}, {"abc123", true}, {"abc", true}, {"a b c", true}, {"abcß", true}, {"abcẞ", false}, {"ABCẞ", false}, {"tr竪s 端ber", true}, {"fooBar", false}, {"123ABC", false}, {"ABC123", false}, {"ABC", false}, {"S T R", false}, {"fooBar", false}, {"abacaba123", true}, } for _, test := range tests { actual := IsLowerCase(test.param) if actual != test.expected { t.Errorf("Expected IsLowerCase(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsUpperCase(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", true}, {"abc123", false}, {"abc", false}, {"a b c", false}, {"abcß", false}, {"abcẞ", false}, {"ABCẞ", true}, {"tr竪s 端ber", false}, {"fooBar", false}, {"123ABC", true}, {"ABC123", true}, {"ABC", true}, {"S T R", true}, {"fooBar", false}, {"abacaba123", false}, } for _, test := range tests { actual := IsUpperCase(test.param) if actual != test.expected { t.Errorf("Expected IsUpperCase(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsInt(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"-2147483648", true}, //Signed 32 Bit Min Int {"2147483647", true}, //Signed 32 Bit Max Int {"-2147483649", true}, //Signed 32 Bit Min Int - 1 {"2147483648", true}, //Signed 32 Bit Max Int + 1 {"4294967295", true}, //Unsigned 32 Bit Max Int {"4294967296", true}, //Unsigned 32 Bit Max Int + 1 {"-9223372036854775808", true}, //Signed 64 Bit Min Int {"9223372036854775807", true}, //Signed 64 Bit Max Int {"-9223372036854775809", true}, //Signed 64 Bit Min Int - 1 {"9223372036854775808", true}, //Signed 64 Bit Max Int + 1 {"18446744073709551615", true}, //Unsigned 64 Bit Max Int {"18446744073709551616", true}, //Unsigned 64 Bit Max Int + 1 {"", true}, {"123", true}, {"0", true}, {"-0", true}, {"+0", true}, {"01", false}, {"123.123", false}, {" ", false}, {"000", false}, } for _, test := range tests { actual := IsInt(test.param) if actual != test.expected { t.Errorf("Expected IsInt(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsHash(t *testing.T) { t.Parallel() var tests = []struct { param string algo string expected bool }{ {"3ca25ae354e192b26879f651a51d92aa8a34d8d3", "sha1", true}, {"3ca25ae354e192b26879f651a51d34d8d3", "sha1", false}, {"3ca25ae354e192b26879f651a51d92aa8a34d8d3", "Tiger160", true}, {"3ca25ae354e192b26879f651a51d34d8d3", "ripemd160", false}, {"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898c", "sha256", true}, {"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha256", false}, {"bf547c3fc5841a377eb1519c2890344dbab15c40ae4150b4b34443d2212e5b04aa9d58865bf03d8ae27840fef430b891", "sha384", true}, {"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha384", false}, {"45bc5fa8cb45ee408c04b6269e9f1e1c17090c5ce26ffeeda2af097735b29953ce547e40ff3ad0d120e5361cc5f9cee35ea91ecd4077f3f589b4d439168f91b9", "sha512", true}, {"579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898casfdsafsadfsdf", "sha512", false}, {"46fc0125a148788a3ac1d649566fc04eb84a746f1a6e4fa7", "tiger192", true}, {"46fc0125a148788a3ac1d649566fc04eb84a746f1a6$$%@^", "TIGER192", false}, {"46fc0125a148788a3ac1d649566fc04eb84a746f1a6$$%@^", "SOMEHASH", false}, } for _, test := range tests { actual := IsHash(test.param, test.algo) if actual != test.expected { t.Errorf("Expected IsHash(%q, %q) to be %v, got %v", test.param, test.algo, test.expected, actual) } } } func TestIsEmail(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"foo@bar.com", true}, {"x@x.x", true}, {"foo@bar.com.au", true}, {"foo+bar@bar.com", true}, {"foo@bar.coffee", true}, {"foo@bar.coffee..coffee", false}, {"foo@bar.bar.coffee", true}, {"foo@bar.中文网", true}, {"invalidemail@", false}, {"invalid.com", false}, {"@invalid.com", false}, {"test|123@m端ller.com", true}, {"hans@m端ller.com", true}, {"hans.m端ller@test.com", true}, {"NathAn.daVIeS@DomaIn.cOM", true}, {"NATHAN.DAVIES@DOMAIN.CO.UK", true}, } for _, test := range tests { actual := IsEmail(test.param) if actual != test.expected { t.Errorf("Expected IsEmail(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsURL(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"http://foo.bar#com", true}, {"http://foobar.com", true}, {"https://foobar.com", true}, {"foobar.com", true}, {"http://foobar.coffee/", true}, {"http://foobar.中文网/", true}, {"http://foobar.org/", true}, {"http://foobar.ORG", true}, {"http://foobar.org:8080/", true}, {"ftp://foobar.ru/", true}, {"ftp.foo.bar", true}, {"http://user:pass@www.foobar.com/", true}, {"http://user:pass@www.foobar.com/path/file", true}, {"http://127.0.0.1/", true}, {"http://duckduckgo.com/?q=%2F", true}, {"http://localhost:3000/", true}, {"http://foobar.com/?foo=bar#baz=qux", true}, {"http://foobar.com?foo=bar", true}, {"http://www.xn--froschgrn-x9a.net/", true}, {"http://foobar.com/a-", true}, {"http://foobar.پاکستان/", true}, {"http://foobar.c_o_m", false}, {"", false}, {"xyz://foobar.com", false}, // {"invalid.", false}, is it false like "localhost."? {".com", false}, {"rtmp://foobar.com", false}, {"http://www.foo_bar.com/", false}, {"http://localhost:3000/", true}, {"http://foobar.com#baz=qux", true}, {"http://foobar.com/t$-_.+!*\\'(),", true}, {"http://www.foobar.com/~foobar", true}, {"http://www.-foobar.com/", false}, {"http://www.foo---bar.com/", false}, {"http://r6---snnvoxuioq6.googlevideo.com", true}, {"mailto:someone@example.com", true}, {"irc://irc.server.org/channel", false}, {"irc://#channel@network", true}, {"/abs/test/dir", false}, {"./rel/test/dir", false}, {"http://foo^bar.org", false}, {"http://foo&*bar.org", false}, {"http://foo&bar.org", false}, {"http://foo bar.org", false}, {"http://foo.bar.org", true}, {"http://www.foo.bar.org", true}, {"http://www.foo.co.uk", true}, {"foo", false}, {"http://.foo.com", false}, {"http://,foo.com", false}, {",foo.com", false}, {"http://myservice.:9093/", true}, // according to issues #62 #66 {"https://pbs.twimg.com/profile_images/560826135676588032/j8fWrmYY_normal.jpeg", true}, // according to #125 {"http://prometheus-alertmanager.service.q:9093", true}, {"aio1_alertmanager_container-63376c45:9093", true}, {"https://www.logn-123-123.url.with.sigle.letter.d:12345/url/path/foo?bar=zzz#user", true}, {"http://me.example.com", true}, {"http://www.me.example.com", true}, {"https://farm6.static.flickr.com", true}, {"https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5", true}, {"google", false}, // According to #87 {"http://hyphenated-host-name.example.co.in", true}, {"http://cant-end-with-hyphen-.example.com", false}, {"http://-cant-start-with-hyphen.example.com", false}, {"http://www.domain-can-have-dashes.com", true}, {"http://m.abcd.com/test.html", true}, {"http://m.abcd.com/a/b/c/d/test.html?args=a&b=c", true}, {"http://[::1]:9093", true}, {"http://[::1]:909388", false}, {"1200::AB00:1234::2552:7777:1313", false}, {"http://[2001:db8:a0b:12f0::1]/index.html", true}, {"http://[1200:0000:AB00:1234:0000:2552:7777:1313]", true}, {"http://user:pass@[::1]:9093/a/b/c/?a=v#abc", true}, {"https://127.0.0.1/a/b/c?a=v&c=11d", true}, {"https://foo_bar.example.com", true}, {"http://foo_bar.example.com", true}, {"http://foo_bar_fizz_buzz.example.com", true}, {"http://_cant_start_with_underescore", false}, {"http://cant_end_with_underescore_", false}, {"foo_bar.example.com", true}, {"foo_bar_fizz_buzz.example.com", true}, {"http://hello_world.example.com", true}, // According to #212 {"foo_bar-fizz-buzz:1313", true}, {"foo_bar-fizz-buzz:13:13", false}, {"foo_bar-fizz-buzz://1313", false}, } for _, test := range tests { actual := IsURL(test.param) if actual != test.expected { t.Errorf("Expected IsURL(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsRequestURL(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"http://foo.bar/#com", true}, {"http://foobar.com", true}, {"https://foobar.com", true}, {"foobar.com", false}, {"http://foobar.coffee/", true}, {"http://foobar.中文网/", true}, {"http://foobar.org/", true}, {"http://foobar.org:8080/", true}, {"ftp://foobar.ru/", true}, {"http://user:pass@www.foobar.com/", true}, {"http://127.0.0.1/", true}, {"http://duckduckgo.com/?q=%2F", true}, {"http://localhost:3000/", true}, {"http://foobar.com/?foo=bar#baz=qux", true}, {"http://foobar.com?foo=bar", true}, {"http://www.xn--froschgrn-x9a.net/", true}, {"", false}, {"xyz://foobar.com", true}, {"invalid.", false}, {".com", false}, {"rtmp://foobar.com", true}, {"http://www.foo_bar.com/", true}, {"http://localhost:3000/", true}, {"http://foobar.com/#baz=qux", true}, {"http://foobar.com/t$-_.+!*\\'(),", true}, {"http://www.foobar.com/~foobar", true}, {"http://www.-foobar.com/", true}, {"http://www.foo---bar.com/", true}, {"mailto:someone@example.com", true}, {"irc://irc.server.org/channel", true}, {"irc://#channel@network", true}, {"/abs/test/dir", false}, {"./rel/test/dir", false}, } for _, test := range tests { actual := IsRequestURL(test.param) if actual != test.expected { t.Errorf("Expected IsRequestURL(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsRequestURI(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"http://foo.bar/#com", true}, {"http://foobar.com", true}, {"https://foobar.com", true}, {"foobar.com", false}, {"http://foobar.coffee/", true}, {"http://foobar.中文网/", true}, {"http://foobar.org/", true}, {"http://foobar.org:8080/", true}, {"ftp://foobar.ru/", true}, {"http://user:pass@www.foobar.com/", true}, {"http://127.0.0.1/", true}, {"http://duckduckgo.com/?q=%2F", true}, {"http://localhost:3000/", true}, {"http://foobar.com/?foo=bar#baz=qux", true}, {"http://foobar.com?foo=bar", true}, {"http://www.xn--froschgrn-x9a.net/", true}, {"xyz://foobar.com", true}, {"invalid.", false}, {".com", false}, {"rtmp://foobar.com", true}, {"http://www.foo_bar.com/", true}, {"http://localhost:3000/", true}, {"http://foobar.com/#baz=qux", true}, {"http://foobar.com/t$-_.+!*\\'(),", true}, {"http://www.foobar.com/~foobar", true}, {"http://www.-foobar.com/", true}, {"http://www.foo---bar.com/", true}, {"mailto:someone@example.com", true}, {"irc://irc.server.org/channel", true}, {"irc://#channel@network", true}, {"/abs/test/dir", true}, {"./rel/test/dir", false}, } for _, test := range tests { actual := IsRequestURI(test.param) if actual != test.expected { t.Errorf("Expected IsRequestURI(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsFloat(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {" ", false}, {"-.123", false}, {"abacaba", false}, {"1f", false}, {"-1f", false}, {"+1f", false}, {"123", true}, {"123.", true}, {"123.123", true}, {"-123.123", true}, {"+123.123", true}, {"0.123", true}, {"-0.123", true}, {"+0.123", true}, {".0", true}, {"01.123", true}, {"-0.22250738585072011e-307", true}, {"+0.22250738585072011e-307", true}, } for _, test := range tests { actual := IsFloat(test.param) if actual != test.expected { t.Errorf("Expected IsFloat(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsHexadecimal(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"abcdefg", false}, {"", false}, {"..", false}, {"deadBEEF", true}, {"ff0044", true}, } for _, test := range tests { actual := IsHexadecimal(test.param) if actual != test.expected { t.Errorf("Expected IsHexadecimal(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsHexcolor(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"#ff", false}, {"fff0", false}, {"#ff12FG", false}, {"CCccCC", true}, {"fff", true}, {"#f00", true}, } for _, test := range tests { actual := IsHexcolor(test.param) if actual != test.expected { t.Errorf("Expected IsHexcolor(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsRGBcolor(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"rgb(0,31,255)", true}, {"rgb(1,349,275)", false}, {"rgb(01,31,255)", false}, {"rgb(0.6,31,255)", false}, {"rgba(0,31,255)", false}, {"rgb(0, 31, 255)", true}, } for _, test := range tests { actual := IsRGBcolor(test.param) if actual != test.expected { t.Errorf("Expected IsRGBcolor(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsNull(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"abacaba", false}, {"", true}, } for _, test := range tests { actual := IsNull(test.param) if actual != test.expected { t.Errorf("Expected IsNull(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsDivisibleBy(t *testing.T) { t.Parallel() var tests = []struct { param1 string param2 string expected bool }{ {"4", "2", true}, {"100", "10", true}, {"", "1", true}, {"123", "foo", false}, {"123", "0", false}, } for _, test := range tests { actual := IsDivisibleBy(test.param1, test.param2) if actual != test.expected { t.Errorf("Expected IsDivisibleBy(%q, %q) to be %v, got %v", test.param1, test.param2, test.expected, actual) } } } // This small example illustrate how to work with IsDivisibleBy function. func ExampleIsDivisibleBy() { println("1024 is divisible by 64: ", IsDivisibleBy("1024", "64")) } func TestIsByteLength(t *testing.T) { t.Parallel() var tests = []struct { param1 string param2 int param3 int expected bool }{ {"abacaba", 100, -1, false}, {"abacaba", 1, 3, false}, {"abacaba", 1, 7, true}, {"abacaba", 0, 8, true}, {"\ufff0", 1, 1, false}, } for _, test := range tests { actual := IsByteLength(test.param1, test.param2, test.param3) if actual != test.expected { t.Errorf("Expected IsByteLength(%q, %q, %q) to be %v, got %v", test.param1, test.param2, test.param3, test.expected, actual) } } } func TestIsJSON(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"145", true}, {"asdf", false}, {"123:f00", false}, {"{\"Name\":\"Alice\",\"Body\":\"Hello\",\"Time\":1294706395881547000}", true}, {"{}", true}, {"{\"Key\":{\"Key\":{\"Key\":123}}}", true}, {"[]", true}, {"null", true}, } for _, test := range tests { actual := IsJSON(test.param) if actual != test.expected { t.Errorf("Expected IsJSON(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsMultibyte(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"abc", false}, {"123", false}, {"<>@;.-=", false}, {"ひらがな・カタカナ、.漢字", true}, {"あいうえお foobar", true}, {"test@example.com", true}, {"test@example.com", true}, {"1234abcDExyz", true}, {"カタカナ", true}, {"", true}, } for _, test := range tests { actual := IsMultibyte(test.param) if actual != test.expected { t.Errorf("Expected IsMultibyte(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsASCII(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", true}, {"foobar", false}, {"xyz098", false}, {"123456", false}, {"カタカナ", false}, {"foobar", true}, {"0987654321", true}, {"test@example.com", true}, {"1234abcDEF", true}, {"", true}, } for _, test := range tests { actual := IsASCII(test.param) if actual != test.expected { t.Errorf("Expected IsASCII(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsPrintableASCII(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", true}, {"foobar", false}, {"xyz098", false}, {"123456", false}, {"カタカナ", false}, {"foobar", true}, {"0987654321", true}, {"test@example.com", true}, {"1234abcDEF", true}, {"newline\n", false}, {"\x19test\x7F", false}, } for _, test := range tests { actual := IsPrintableASCII(test.param) if actual != test.expected { t.Errorf("Expected IsPrintableASCII(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsFullWidth(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", true}, {"abc", false}, {"abc123", false}, {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false}, {"ひらがな・カタカナ、.漢字", true}, {"3ー0 a@com", true}, {"Fカタカナ゙ᆲ", true}, {"Good=Parts", true}, {"", true}, } for _, test := range tests { actual := IsFullWidth(test.param) if actual != test.expected { t.Errorf("Expected IsFullWidth(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsHalfWidth(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", true}, {"あいうえお", false}, {"0011", false}, {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", true}, {"l-btn_02--active", true}, {"abc123い", true}, {"カタカナ゙ᆲ←", true}, {"", true}, } for _, test := range tests { actual := IsHalfWidth(test.param) if actual != test.expected { t.Errorf("Expected IsHalfWidth(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsVariableWidth(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", true}, {"ひらがなカタカナ漢字ABCDE", true}, {"3ー0123", true}, {"Fカタカナ゙ᆲ", true}, {"", true}, {"Good=Parts", true}, {"abc", false}, {"abc123", false}, {"!\"#$%&()<>/+=-_? ~^|.,@`{}[]", false}, {"ひらがな・カタカナ、.漢字", false}, {"123456", false}, {"カタカナ゙ᆲ", false}, } for _, test := range tests { actual := IsVariableWidth(test.param) if actual != test.expected { t.Errorf("Expected IsVariableWidth(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsUUID(t *testing.T) { t.Parallel() // Tests without version var tests = []struct { param string expected bool }{ {"", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, {"a987fbc94bed3078cf079141ba07c9f3", false}, {"934859", false}, {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false}, {"aaaaaaaa-1111-1111-aaag-111111111111", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, } for _, test := range tests { actual := IsUUID(test.param) if actual != test.expected { t.Errorf("Expected IsUUID(%q) to be %v, got %v", test.param, test.expected, actual) } } // UUID ver. 3 tests = []struct { param string expected bool }{ {"", false}, {"412452646", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, } for _, test := range tests { actual := IsUUIDv3(test.param) if actual != test.expected { t.Errorf("Expected IsUUIDv3(%q) to be %v, got %v", test.param, test.expected, actual) } } // UUID ver. 4 tests = []struct { param string expected bool }{ {"", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false}, {"934859", false}, {"57b73598-8764-4ad0-a76a-679bb6640eb1", true}, {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true}, } for _, test := range tests { actual := IsUUIDv4(test.param) if actual != test.expected { t.Errorf("Expected IsUUIDv4(%q) to be %v, got %v", test.param, test.expected, actual) } } // UUID ver. 5 tests = []struct { param string expected bool }{ {"", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"9c858901-8a57-4791-81fe-4c455b099bc9", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"987fbc97-4bed-5078-af07-9141ba07c9f3", true}, {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true}, } for _, test := range tests { actual := IsUUIDv5(test.param) if actual != test.expected { t.Errorf("Expected IsUUIDv5(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsCreditCard(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"foo", false}, {"5398228707871528", false}, {"375556917985515", true}, {"36050234196908", true}, {"4716461583322103", true}, {"4716-2210-5188-5662", true}, {"4929 7226 5379 7141", true}, {"5398228707871527", true}, } for _, test := range tests { actual := IsCreditCard(test.param) if actual != test.expected { t.Errorf("Expected IsCreditCard(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsISBN(t *testing.T) { t.Parallel() // Without version var tests = []struct { param string expected bool }{ {"", false}, {"foo", false}, {"3836221195", true}, {"1-61729-085-8", true}, {"3 423 21412 0", true}, {"3 401 01319 X", true}, {"9784873113685", true}, {"978-4-87311-368-5", true}, {"978 3401013190", true}, {"978-3-8362-2119-1", true}, } for _, test := range tests { actual := IsISBN(test.param, -1) if actual != test.expected { t.Errorf("Expected IsISBN(%q, -1) to be %v, got %v", test.param, test.expected, actual) } } // ISBN 10 tests = []struct { param string expected bool }{ {"", false}, {"foo", false}, {"3423214121", false}, {"978-3836221191", false}, {"3-423-21412-1", false}, {"3 423 21412 1", false}, {"3836221195", true}, {"1-61729-085-8", true}, {"3 423 21412 0", true}, {"3 401 01319 X", true}, } for _, test := range tests { actual := IsISBN10(test.param) if actual != test.expected { t.Errorf("Expected IsISBN10(%q) to be %v, got %v", test.param, test.expected, actual) } } // ISBN 13 tests = []struct { param string expected bool }{ {"", false}, {"foo", false}, {"3-8362-2119-5", false}, {"01234567890ab", false}, {"978 3 8362 2119 0", false}, {"9784873113685", true}, {"978-4-87311-368-5", true}, {"978 3401013190", true}, {"978-3-8362-2119-1", true}, } for _, test := range tests { actual := IsISBN13(test.param) if actual != test.expected { t.Errorf("Expected IsISBN13(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsDataURI(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, {"data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true}, {"data:image/png;base64,12345", false}, {"", false}, {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, } for _, test := range tests { actual := IsDataURI(test.param) if actual != test.expected { t.Errorf("Expected IsDataURI(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsBase64(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, {"Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, {"U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", true}, {"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true}, {"12345", false}, {"", false}, {"Vml2YW11cyBmZXJtZtesting123", false}, } for _, test := range tests { actual := IsBase64(test.param) if actual != test.expected { t.Errorf("Expected IsBase64(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsISO3166Alpha2(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"ABCD", false}, {"A", false}, {"AC", false}, {"AP", false}, {"GER", false}, {"NU", true}, {"DE", true}, {"JP", true}, {"JPN", false}, {"ZWE", false}, {"GER", false}, {"DEU", false}, } for _, test := range tests { actual := IsISO3166Alpha2(test.param) if actual != test.expected { t.Errorf("Expected IsISO3166Alpha2(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsISO3166Alpha3(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"ABCD", false}, {"A", false}, {"AC", false}, {"AP", false}, {"NU", false}, {"DE", false}, {"JP", false}, {"ZWE", true}, {"JPN", true}, {"GER", false}, {"DEU", true}, } for _, test := range tests { actual := IsISO3166Alpha3(test.param) if actual != test.expected { t.Errorf("Expected IsISO3166Alpha3(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsISO693Alpha2(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"abcd", false}, {"a", false}, {"ac", false}, {"ap", false}, {"de", true}, {"DE", false}, {"mk", true}, {"mac", false}, {"sw", true}, {"SW", false}, {"ger", false}, {"deu", false}, } for _, test := range tests { actual := IsISO693Alpha2(test.param) if actual != test.expected { t.Errorf("Expected IsISO693Alpha2(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsISO693Alpha3b(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"abcd", false}, {"a", false}, {"ac", false}, {"ap", false}, {"de", false}, {"DE", false}, {"mkd", false}, {"mac", true}, {"sw", false}, {"SW", false}, {"ger", true}, {"deu", false}, } for _, test := range tests { actual := IsISO693Alpha3b(test.param) if actual != test.expected { t.Errorf("Expected IsISO693Alpha3b(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsIP(t *testing.T) { t.Parallel() // Without version var tests = []struct { param string expected bool }{ {"", false}, {"127.0.0.1", true}, {"0.0.0.0", true}, {"255.255.255.255", true}, {"1.2.3.4", true}, {"::1", true}, {"2001:db8:0000:1:1:1:1:1", true}, {"300.0.0.0", false}, } for _, test := range tests { actual := IsIP(test.param) if actual != test.expected { t.Errorf("Expected IsIP(%q) to be %v, got %v", test.param, test.expected, actual) } } // IPv4 tests = []struct { param string expected bool }{ {"", false}, {"127.0.0.1", true}, {"0.0.0.0", true}, {"255.255.255.255", true}, {"1.2.3.4", true}, {"::1", false}, {"2001:db8:0000:1:1:1:1:1", false}, {"300.0.0.0", false}, } for _, test := range tests { actual := IsIPv4(test.param) if actual != test.expected { t.Errorf("Expected IsIPv4(%q) to be %v, got %v", test.param, test.expected, actual) } } // IPv6 tests = []struct { param string expected bool }{ {"", false}, {"127.0.0.1", false}, {"0.0.0.0", false}, {"255.255.255.255", false}, {"1.2.3.4", false}, {"::1", true}, {"2001:db8:0000:1:1:1:1:1", true}, {"300.0.0.0", false}, } for _, test := range tests { actual := IsIPv6(test.param) if actual != test.expected { t.Errorf("Expected IsIPv6(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsPort(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"1", true}, {"65535", true}, {"0", false}, {"65536", false}, {"65538", false}, } for _, test := range tests { actual := IsPort(test.param) if actual != test.expected { t.Errorf("Expected IsPort(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsDNSName(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"localhost", true}, {"a.bc", true}, {"a.b.", true}, {"a.b..", false}, {"localhost.local", true}, {"localhost.localdomain.intern", true}, {"l.local.intern", true}, {"ru.link.n.svpncloud.com", true}, {"-localhost", false}, {"localhost.-localdomain", false}, {"localhost.localdomain.-int", false}, {"_localhost", true}, {"localhost._localdomain", true}, {"localhost.localdomain._int", true}, {"lÖcalhost", false}, {"localhost.lÖcaldomain", false}, {"localhost.localdomain.üntern", false}, {"__", true}, {"localhost/", false}, {"127.0.0.1", false}, {"[::1]", false}, {"50.50.50.50", false}, {"localhost.localdomain.intern:65535", false}, {"漢字汉字", false}, {"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de", false}, } for _, test := range tests { actual := IsDNSName(test.param) if actual != test.expected { t.Errorf("Expected IsDNS(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsHost(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"localhost", true}, {"localhost.localdomain", true}, {"2001:db8:0000:1:1:1:1:1", true}, {"::1", true}, {"play.golang.org", true}, {"localhost.localdomain.intern:65535", false}, {"-[::1]", false}, {"-localhost", false}, {".localhost", false}, } for _, test := range tests { actual := IsHost(test.param) if actual != test.expected { t.Errorf("Expected IsHost(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsDialString(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"localhost.local:1", true}, {"localhost.localdomain:9090", true}, {"localhost.localdomain.intern:65535", true}, {"127.0.0.1:30000", true}, {"[::1]:80", true}, {"[1200::AB00:1234::2552:7777:1313]:22", false}, {"-localhost:1", false}, {"localhost.-localdomain:9090", false}, {"localhost.localdomain.-int:65535", false}, {"localhost.loc:100000", false}, {"漢字汉字:2", false}, {"www.jubfvq1v3p38i51622y0dvmdk1mymowjyeu26gbtw9andgynj1gg8z3msb1kl5z6906k846pj3sulm4kiyk82ln5teqj9nsht59opr0cs5ssltx78lfyvml19lfq1wp4usbl0o36cmiykch1vywbttcus1p9yu0669h8fj4ll7a6bmop505908s1m83q2ec2qr9nbvql2589adma3xsq2o38os2z3dmfh2tth4is4ixyfasasasefqwe4t2ub2fz1rme.de:20000", false}, } for _, test := range tests { actual := IsDialString(test.param) if actual != test.expected { t.Errorf("Expected IsDialString(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsMAC(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"3D:F2:C9:A6:B3:4F", true}, {"3D-F2-C9-A6-B3:4F", false}, {"123", false}, {"", false}, {"abacaba", false}, } for _, test := range tests { actual := IsMAC(test.param) if actual != test.expected { t.Errorf("Expected IsMAC(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestFilePath(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool osType int }{ {"c:\\" + strings.Repeat("a", 32767), true, Win}, //See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath {"c:\\" + strings.Repeat("a", 32768), false, Win}, {"c:\\path\\file (x86)\bar", true, Win}, {"c:\\path\\file", true, Win}, {"c:\\path\\file:exe", false, Unknown}, {"C:\\", true, Win}, {"c:\\path\\file\\", true, Win}, {"c:/path/file/", false, Unknown}, {"/path/file/", true, Unix}, {"/path/file:SAMPLE/", true, Unix}, {"/path/file:/.txt", true, Unix}, {"/path", true, Unix}, {"/path/__bc/file.txt", true, Unix}, {"/path/a--ac/file.txt", true, Unix}, {"/_path/file.txt", true, Unix}, {"/path/__bc/file.txt", true, Unix}, {"/path/a--ac/file.txt", true, Unix}, {"/__path/--file.txt", true, Unix}, {"/path/a bc", true, Unix}, } for _, test := range tests { actual, osType := IsFilePath(test.param) if actual != test.expected || osType != test.osType { t.Errorf("Expected IsFilePath(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsLatitude(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"-90.000", true}, {"+90", true}, {"47.1231231", true}, {"+99.9", false}, {"108", false}, } for _, test := range tests { actual := IsLatitude(test.param) if actual != test.expected { t.Errorf("Expected IsLatitude(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsLongitude(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"-180.000", true}, {"180.1", false}, {"+73.234", true}, {"+382.3811", false}, {"23.11111111", true}, } for _, test := range tests { actual := IsLongitude(test.param) if actual != test.expected { t.Errorf("Expected IsLongitude(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsSSN(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"00-90-8787", false}, {"66690-76", false}, {"191 60 2869", true}, {"191-60-2869", true}, } for _, test := range tests { actual := IsSSN(test.param) if actual != test.expected { t.Errorf("Expected IsSSN(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsMongoID(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"507f1f77bcf86cd799439011", true}, {"507f1f77bcf86cd7994390", false}, {"507f1f77bcf86cd79943901z", false}, {"507f1f77bcf86cd799439011 ", false}, {"", false}, } for _, test := range tests { actual := IsMongoID(test.param) if actual != test.expected { t.Errorf("Expected IsMongoID(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsSemver(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"v1.0.0", true}, {"1.0.0", true}, {"1.1.01", false}, {"1.01.0", false}, {"01.1.0", false}, {"v1.1.01", false}, {"v1.01.0", false}, {"v01.1.0", false}, {"1.0.0-alpha", true}, {"1.0.0-alpha.1", true}, {"1.0.0-0.3.7", true}, {"1.0.0-0.03.7", false}, {"1.0.0-00.3.7", false}, {"1.0.0-x.7.z.92", true}, {"1.0.0-alpha+001", true}, {"1.0.0+20130313144700", true}, {"1.0.0-beta+exp.sha.5114f85", true}, {"1.0.0-beta+exp.sha.05114f85", true}, {"1.0.0-+beta", false}, {"1.0.0-b+-9+eta", false}, {"v+1.8.0-b+-9+eta", false}, } for _, test := range tests { actual := IsSemver(test.param) if actual != test.expected { t.Errorf("Expected IsSemver(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsTime(t *testing.T) { t.Parallel() var tests = []struct { param string format string expected bool }{ {"2016-12-31 11:00", time.RFC3339, false}, {"2016-12-31 11:00:00", time.RFC3339, false}, {"2016-12-31T11:00", time.RFC3339, false}, {"2016-12-31T11:00:00", time.RFC3339, false}, {"2016-12-31T11:00:00Z", time.RFC3339, true}, {"2016-12-31T11:00:00+01:00", time.RFC3339, true}, {"2016-12-31T11:00:00-01:00", time.RFC3339, true}, {"2016-12-31T11:00:00.05Z", time.RFC3339, true}, {"2016-12-31T11:00:00.05-01:00", time.RFC3339, true}, {"2016-12-31T11:00:00.05+01:00", time.RFC3339, true}, {"2016-12-31T11:00:00", RF3339WithoutZone, true}, {"2016-12-31T11:00:00Z", RF3339WithoutZone, false}, {"2016-12-31T11:00:00+01:00", RF3339WithoutZone, false}, {"2016-12-31T11:00:00-01:00", RF3339WithoutZone, false}, {"2016-12-31T11:00:00.05Z", RF3339WithoutZone, false}, {"2016-12-31T11:00:00.05-01:00", RF3339WithoutZone, false}, {"2016-12-31T11:00:00.05+01:00", RF3339WithoutZone, false}, } for _, test := range tests { actual := IsTime(test.param, test.format) if actual != test.expected { t.Errorf("Expected IsTime(%q, time.RFC3339) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsRFC3339(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"2016-12-31 11:00", false}, {"2016-12-31 11:00:00", false}, {"2016-12-31T11:00", false}, {"2016-12-31T11:00:00", false}, {"2016-12-31T11:00:00Z", true}, {"2016-12-31T11:00:00+01:00", true}, {"2016-12-31T11:00:00-01:00", true}, {"2016-12-31T11:00:00.05Z", true}, {"2016-12-31T11:00:00.05-01:00", true}, {"2016-12-31T11:00:00.05+01:00", true}, } for _, test := range tests { actual := IsRFC3339(test.param) if actual != test.expected { t.Errorf("Expected IsRFC3339(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestIsISO4217(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"", false}, {"ABCD", false}, {"A", false}, {"ZZZ", false}, {"usd", false}, {"USD", true}, } for _, test := range tests { actual := IsISO4217(test.param) if actual != test.expected { t.Errorf("Expected IsISO4217(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestByteLength(t *testing.T) { t.Parallel() var tests = []struct { value string min string max string expected bool }{ {"123456", "0", "100", true}, {"1239999", "0", "0", false}, {"1239asdfasf99", "100", "200", false}, {"1239999asdff29", "10", "30", true}, {"你", "0", "1", false}, } for _, test := range tests { actual := ByteLength(test.value, test.min, test.max) if actual != test.expected { t.Errorf("Expected ByteLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual) } } } func TestRuneLength(t *testing.T) { t.Parallel() var tests = []struct { value string min string max string expected bool }{ {"123456", "0", "100", true}, {"1239999", "0", "0", false}, {"1239asdfasf99", "100", "200", false}, {"1239999asdff29", "10", "30", true}, {"你", "0", "1", true}, } for _, test := range tests { actual := RuneLength(test.value, test.min, test.max) if actual != test.expected { t.Errorf("Expected RuneLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual) } } } func TestStringLength(t *testing.T) { t.Parallel() var tests = []struct { value string min string max string expected bool }{ {"123456", "0", "100", true}, {"1239999", "0", "0", false}, {"1239asdfasf99", "100", "200", false}, {"1239999asdff29", "10", "30", true}, {"あいうえお", "0", "5", true}, {"あいうえおか", "0", "5", false}, {"あいうえお", "0", "0", false}, {"あいうえ", "5", "10", false}, } for _, test := range tests { actual := StringLength(test.value, test.min, test.max) if actual != test.expected { t.Errorf("Expected StringLength(%s, %s, %s) to be %v, got %v", test.value, test.min, test.max, test.expected, actual) } } } func TestIsIn(t *testing.T) { t.Parallel() var tests = []struct { value string params []string expected bool }{ {"PRESENT", []string{"PRESENT"}, true}, {"PRESENT", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, true}, {"PRÉSENTE", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, true}, {"PRESENT", []string{}, false}, {"PRESENT", nil, false}, {"ABSENT", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, false}, {"", []string{"PRESENT", "PRÉSENTE", "NOTABSENT"}, false}, } for _, test := range tests { actual := IsIn(test.value, test.params...) if actual != test.expected { t.Errorf("Expected IsIn(%s, %v) to be %v, got %v", test.value, test.params, test.expected, actual) } } } type Address struct { Street string `valid:"-"` Zip string `json:"zip" valid:"numeric,required"` } type User struct { Name string `valid:"required"` Email string `valid:"required,email"` Password string `valid:"required"` Age int `valid:"required,numeric,@#\u0000"` Home *Address Work []Address } type UserValid struct { Name string `valid:"required"` Email string `valid:"required,email"` Password string `valid:"required"` Age int `valid:"required"` Home *Address Work []Address `valid:"required"` } type PrivateStruct struct { privateField string `valid:"required,alpha,d_k"` NonZero int ListInt []int ListString []string `valid:"alpha"` Work [2]Address Home Address Map map[string]Address } type NegationStruct struct { NotInt string `valid:"!int"` Int string `valid:"int"` } type LengthStruct struct { Length string `valid:"length(10|20)"` } type StringLengthStruct struct { Length string `valid:"stringlength(10|20)"` } type StringMatchesStruct struct { StringMatches string `valid:"matches(^[0-9]{3}$)"` } // TODO: this testcase should be fixed // type StringMatchesComplexStruct struct { // StringMatches string `valid:"matches(^\\$\\([\"']\\w+[\"']\\)$)"` // } type IsInStruct struct { IsIn string `valid:"in(PRESENT|PRÉSENTE|NOTABSENT)"` } type Post struct { Title string `valid:"alpha,required"` Message string `valid:"ascii"` AuthorIP string `valid:"ipv4"` } type MissingValidationDeclarationStruct struct { Name string `` Email string `valid:"required,email"` } type FieldsRequiredByDefaultButExemptStruct struct { Name string `valid:"-"` Email string `valid:"email"` } type FieldsRequiredByDefaultButExemptOrOptionalStruct struct { Name string `valid:"-"` Email string `valid:"optional,email"` } type MessageWithSeveralFieldsStruct struct { Title string `valid:"length(1|10)"` Body string `valid:"length(1|10)"` } func TestValidateMissingValidationDeclarationStruct(t *testing.T) { var tests = []struct { param MissingValidationDeclarationStruct expected bool }{ {MissingValidationDeclarationStruct{}, false}, {MissingValidationDeclarationStruct{Name: "TEST", Email: "test@example.com"}, false}, } SetFieldsRequiredByDefault(true) for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } SetFieldsRequiredByDefault(false) } func TestFieldsRequiredByDefaultButExemptStruct(t *testing.T) { var tests = []struct { param FieldsRequiredByDefaultButExemptStruct expected bool }{ {FieldsRequiredByDefaultButExemptStruct{}, false}, {FieldsRequiredByDefaultButExemptStruct{Name: "TEST"}, false}, {FieldsRequiredByDefaultButExemptStruct{Email: ""}, false}, {FieldsRequiredByDefaultButExemptStruct{Email: "test@example.com"}, true}, } SetFieldsRequiredByDefault(true) for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } SetFieldsRequiredByDefault(false) } func TestFieldsRequiredByDefaultButExemptOrOptionalStruct(t *testing.T) { var tests = []struct { param FieldsRequiredByDefaultButExemptOrOptionalStruct expected bool }{ {FieldsRequiredByDefaultButExemptOrOptionalStruct{}, true}, {FieldsRequiredByDefaultButExemptOrOptionalStruct{Name: "TEST"}, true}, {FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: ""}, true}, {FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: "test@example.com"}, true}, {FieldsRequiredByDefaultButExemptOrOptionalStruct{Email: "test@example"}, false}, } SetFieldsRequiredByDefault(true) for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } SetFieldsRequiredByDefault(false) } func TestInvalidValidator(t *testing.T) { type InvalidStruct struct { Field int `valid:"someInvalidValidator"` } invalidStruct := InvalidStruct{1} if valid, err := ValidateStruct(&invalidStruct); valid || err == nil || err.Error() != `Field: The following validator is invalid or can't be applied to the field: "someInvalidValidator"` { t.Errorf("Got an unexpected result for struct with invalid validator: %t %s", valid, err) } } func TestCustomValidator(t *testing.T) { type ValidStruct struct { Field int `valid:"customTrueValidator"` } type InvalidStruct struct { Field int `valid:"customFalseValidator~Custom validator error"` } type StructWithCustomAndBuiltinValidator struct { Field int `valid:"customTrueValidator,required"` } if valid, err := ValidateStruct(&ValidStruct{Field: 1}); !valid || err != nil { t.Errorf("Got an unexpected result for struct with custom always true validator: %t %s", valid, err) } if valid, err := ValidateStruct(&InvalidStruct{Field: 1}); valid || err == nil || err.Error() != "Custom validator error" { t.Errorf("Got an unexpected result for struct with custom always false validator: %t %s", valid, err) } mixedStruct := StructWithCustomAndBuiltinValidator{} if valid, err := ValidateStruct(&mixedStruct); valid || err == nil || err.Error() != "Field: non zero value required" { t.Errorf("Got an unexpected result for invalid struct with custom and built-in validators: %t %s", valid, err) } mixedStruct.Field = 1 if valid, err := ValidateStruct(&mixedStruct); !valid || err != nil { t.Errorf("Got an unexpected result for valid struct with custom and built-in validators: %t %s", valid, err) } } type CustomByteArray [6]byte type StructWithCustomByteArray struct { ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` Email string `valid:"email"` CustomMinLength int `valid:"-"` } func TestStructWithCustomByteArray(t *testing.T) { t.Parallel() // add our custom byte array validator that fails when the byte array is pristine (all zeroes) CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { switch v := o.(type) { case StructWithCustomByteArray: if len(v.Email) > 0 { if v.Email != "test@example.com" { t.Errorf("v.Email should have been 'test@example.com' but was '%s'", v.Email) } } default: t.Errorf("Context object passed to custom validator should have been a StructWithCustomByteArray but was %T (%+v)", o, o) } switch v := i.(type) { case CustomByteArray: for _, e := range v { // check if v is empty, i.e. all zeroes if e != 0 { return true } } } return false })) CustomTypeTagMap.Set("customMinLengthValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool { switch v := o.(type) { case StructWithCustomByteArray: return len(v.ID) >= v.CustomMinLength } return false })) testCustomByteArray := CustomByteArray{'1', '2', '3', '4', '5', '6'} var tests = []struct { param StructWithCustomByteArray expected bool }{ {StructWithCustomByteArray{}, false}, {StructWithCustomByteArray{Email: "test@example.com"}, false}, {StructWithCustomByteArray{ID: testCustomByteArray, Email: "test@example.com"}, true}, {StructWithCustomByteArray{ID: testCustomByteArray, Email: "test@example.com", CustomMinLength: 7}, false}, } SetFieldsRequiredByDefault(true) for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } SetFieldsRequiredByDefault(false) } func TestValidateNegationStruct(t *testing.T) { var tests = []struct { param NegationStruct expected bool }{ {NegationStruct{"a1", "11"}, true}, {NegationStruct{"email@email.email", "11"}, true}, {NegationStruct{"123456----", "11"}, true}, {NegationStruct{"::1", "11"}, true}, {NegationStruct{"123.123", "11"}, true}, {NegationStruct{"a1", "a1"}, false}, {NegationStruct{"11", "a1"}, false}, {NegationStruct{"11", "11"}, false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestLengthStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {LengthStruct{"11111"}, false}, {LengthStruct{"11111111111111111110000000000000000"}, false}, {LengthStruct{"11dfffdf0099"}, true}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestStringLengthStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {StringLengthStruct{"11111"}, false}, {StringLengthStruct{"11111111111111111110000000000000000"}, false}, {StringLengthStruct{"11dfffdf0099"}, true}, {StringLengthStruct{"あいうえお"}, false}, {StringLengthStruct{"あいうえおかきくけこ"}, true}, {StringLengthStruct{"あいうえおかきくけこさしすせそたちつてと"}, true}, {StringLengthStruct{"あいうえおかきくけこさしすせそたちつてとな"}, false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestStringMatchesStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {StringMatchesStruct{"123"}, true}, {StringMatchesStruct{"123456"}, false}, {StringMatchesStruct{"123abcd"}, false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestIsInStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {IsInStruct{"PRESENT"}, true}, {IsInStruct{""}, true}, {IsInStruct{" "}, false}, {IsInStruct{"ABSENT"}, false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestRequiredIsInStruct(t *testing.T) { type RequiredIsInStruct struct { IsIn string `valid:"in(PRESENT|PRÉSENTE|NOTABSENT),required"` } var tests = []struct { param interface{} expected bool }{ {RequiredIsInStruct{"PRESENT"}, true}, {RequiredIsInStruct{""}, false}, {RequiredIsInStruct{" "}, false}, {RequiredIsInStruct{"ABSENT"}, false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestEmptyRequiredIsInStruct(t *testing.T) { type EmptyRequiredIsInStruct struct { IsIn string `valid:"in(),required"` } var tests = []struct { param interface{} expected bool }{ {EmptyRequiredIsInStruct{"PRESENT"}, false}, {EmptyRequiredIsInStruct{""}, false}, {EmptyRequiredIsInStruct{" "}, false}, {EmptyRequiredIsInStruct{"ABSENT"}, false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestFunkyIsInStruct(t *testing.T) { type FunkyIsInStruct struct { IsIn string `valid:"in(PRESENT|| |PRÉSENTE|NOTABSENT)"` } var tests = []struct { param interface{} expected bool }{ {FunkyIsInStruct{"PRESENT"}, true}, {FunkyIsInStruct{""}, true}, {FunkyIsInStruct{" "}, true}, {FunkyIsInStruct{"ABSENT"}, false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } // TODO: test case broken // func TestStringMatchesComplexStruct(t *testing.T) { // var tests = []struct { // param interface{} // expected bool // }{ // {StringMatchesComplexStruct{"$()"}, false}, // {StringMatchesComplexStruct{"$('AZERTY')"}, true}, // {StringMatchesComplexStruct{`$("AZERTY")`}, true}, // {StringMatchesComplexStruct{`$("")`}, false}, // {StringMatchesComplexStruct{"AZERTY"}, false}, // {StringMatchesComplexStruct{"$AZERTY"}, false}, // } // for _, test := range tests { // actual, err := ValidateStruct(test.param) // if actual != test.expected { // t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) // if err != nil { // t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) // } // } // } // } func TestValidateStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {User{"John", "john@yahoo.com", "123G#678", 20, &Address{"Street", "123456"}, []Address{{"Street", "123456"}, {"Street", "123456"}}}, false}, {User{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, {User{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, {UserValid{"John", "john@yahoo.com", "123G#678", 20, &Address{"Street", "123456"}, []Address{{"Street", "123456"}, {"Street", "123456"}}}, true}, {UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{}}, false}, {UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, {UserValid{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{{"Street", "ABC456D89"}, {"Street", "123456"}}}, false}, {nil, true}, {User{"John", "john@yahoo.com", "123G#678", 0, &Address{"Street", "123456"}, []Address{}}, false}, {"im not a struct", false}, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } TagMap["d_k"] = Validator(func(str string) bool { return str == "d_k" }) result, err := ValidateStruct(PrivateStruct{"d_k", 0, []int{1, 2}, []string{"hi", "super"}, [2]Address{{"Street", "123456"}, {"Street", "123456"}}, Address{"Street", "123456"}, map[string]Address{"address": {"Street", "123456"}}}) if result != true { t.Log("Case ", 6, ": expected ", true, " when result is ", result) t.Error(err) t.FailNow() } } type testByteArray [8]byte type testByteMap map[byte]byte type testByteSlice []byte type testStringStringMap map[string]string type testStringIntMap map[string]int func TestRequired(t *testing.T) { testString := "foobar" var tests = []struct { param interface{} expected bool }{ { struct { Pointer *string `valid:"required"` }{}, false, }, { struct { Pointer *string `valid:"required"` }{ Pointer: &testString, }, true, }, { struct { Addr Address `valid:"required"` }{}, false, }, { struct { Addr Address `valid:"required"` }{ Addr: Address{"", "123"}, }, true, }, { struct { Pointer *Address `valid:"required"` }{}, false, }, { struct { Pointer *Address `valid:"required"` }{ Pointer: &Address{"", "123"}, }, true, }, { struct { TestByteArray testByteArray `valid:"required"` }{}, false, }, { struct { TestByteArray testByteArray `valid:"required"` }{ testByteArray{}, }, false, }, { struct { TestByteArray testByteArray `valid:"required"` }{ testByteArray{'1', '2', '3', '4', '5', '6', '7', 'A'}, }, true, }, { struct { TestByteMap testByteMap `valid:"required"` }{}, false, }, { struct { TestByteSlice testByteSlice `valid:"required"` }{}, false, }, { struct { TestStringStringMap testStringStringMap `valid:"required"` }{ testStringStringMap{"test": "test"}, }, true, }, { struct { TestIntMap testStringIntMap `valid:"required"` }{ testStringIntMap{"test": 42}, }, true, }, } for _, test := range tests { actual, err := ValidateStruct(test.param) if actual != test.expected { t.Errorf("Expected ValidateStruct(%q) to be %v, got %v", test.param, test.expected, actual) if err != nil { t.Errorf("Got Error on ValidateStruct(%q): %s", test.param, err) } } } } func TestErrorByField(t *testing.T) { t.Parallel() var tests = []struct { param string expected string }{ {"message", ""}, {"Message", ""}, {"title", ""}, {"Title", "My123 does not validate as alpha"}, {"AuthorIP", "123 does not validate as ipv4"}, } post := &Post{"My123", "duck13126", "123"} _, err := ValidateStruct(post) for _, test := range tests { actual := ErrorByField(err, test.param) if actual != test.expected { t.Errorf("Expected ErrorByField(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestErrorsByField(t *testing.T) { t.Parallel() var tests = []struct { param string expected string }{ {"Title", "My123 does not validate as alpha"}, {"AuthorIP", "123 does not validate as ipv4"}, } post := &Post{Title: "My123", Message: "duck13126", AuthorIP: "123"} _, err := ValidateStruct(post) errs := ErrorsByField(err) if len(errs) != 2 { t.Errorf("There should only be 2 errors but got %v", len(errs)) } for _, test := range tests { if actual, ok := errs[test.param]; !ok || actual != test.expected { t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) } } tests = []struct { param string expected string }{ {"Title", ";:;message;:; does not validate as length(1|10)"}, {"Body", ";:;message;:; does not validate as length(1|10)"}, } message := &MessageWithSeveralFieldsStruct{Title: ";:;message;:;", Body: ";:;message;:;"} _, err = ValidateStruct(message) errs = ErrorsByField(err) if len(errs) != 2 { t.Errorf("There should only be 2 errors but got %v", len(errs)) } for _, test := range tests { if actual, ok := errs[test.param]; !ok || actual != test.expected { t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) } } tests = []struct { param string expected string }{ {"CustomField", "An error occurred"}, } err = Error{"CustomField", fmt.Errorf("An error occurred"), false, "hello"} errs = ErrorsByField(err) if len(errs) != 1 { t.Errorf("There should only be 1 errors but got %v", len(errs)) } for _, test := range tests { if actual, ok := errs[test.param]; !ok || actual != test.expected { t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) } } type StructWithCustomValidation struct { Email string `valid:"email"` ID string `valid:"falseValidation"` } CustomTypeTagMap.Set("falseValidation", CustomTypeValidator(func(i interface{}, o interface{}) bool { return false })) tests = []struct { param string expected string }{ {"Email", "My123 does not validate as email"}, {"ID", "duck13126 does not validate as falseValidation"}, } s := &StructWithCustomValidation{Email: "My123", ID: "duck13126"} _, err = ValidateStruct(s) errs = ErrorsByField(err) if len(errs) != 2 { t.Errorf("There should only be 2 errors but got %v", len(errs)) } for _, test := range tests { if actual, ok := errs[test.param]; !ok || actual != test.expected { t.Errorf("Expected ErrorsByField(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestValidateStructPointers(t *testing.T) { // Struct which uses pointers for values type UserWithPointers struct { Name *string `valid:"-"` Email *string `valid:"email"` FavoriteFood *string `valid:"length(0|32)"` Nerd *bool `valid:"-"` } var tests = []struct { param string expected string }{ {"Name", ""}, {"Email", "invalid does not validate as email"}, {"FavoriteFood", ""}, {"Nerd", ""}, } name := "Herman" email := "invalid" food := "Pizza" nerd := true user := &UserWithPointers{&name, &email, &food, &nerd} _, err := ValidateStruct(user) for _, test := range tests { actual := ErrorByField(err, test.param) if actual != test.expected { t.Errorf("Expected ErrorByField(%q) to be %v, got %v", test.param, test.expected, actual) } } } func ExampleValidateStruct() { type Post struct { Title string `valid:"alphanum,required"` Message string `valid:"duck,ascii"` AuthorIP string `valid:"ipv4"` } post := &Post{"My Example Post", "duck", "123.234.54.3"} //Add your own struct validation tags TagMap["duck"] = Validator(func(str string) bool { return str == "duck" }) result, err := ValidateStruct(post) if err != nil { println("error: " + err.Error()) } println(result) } func TestIsCIDR(t *testing.T) { t.Parallel() var tests = []struct { param string expected bool }{ {"193.168.3.20/7", true}, {"2001:db8::/32", true}, {"2001:0db8:85a3:0000:0000:8a2e:0370:7334/64", true}, {"193.138.3.20/60", false}, {"500.323.2.23/43", false}, {"", false}, } for _, test := range tests { actual := IsCIDR(test.param) if actual != test.expected { t.Errorf("Expected IsCIDR(%q) to be %v, got %v", test.param, test.expected, actual) } } } func TestOptionalCustomValidators(t *testing.T) { CustomTypeTagMap.Set("f2", CustomTypeValidator(func(i interface{}, o interface{}) bool { return false })) var val struct { WithCustomError string `valid:"f2~boom,optional"` WithoutCustomError string `valid:"f2,optional"` OptionalFirst string `valid:"optional,f2"` } ok, err := ValidateStruct(val) if err != nil { t.Errorf("Expected nil err with optional validation, got %v", err) } if !ok { t.Error("Expected validation to return true, got false") } } func TestJSONValidator(t *testing.T) { var val struct { WithJSONName string `json:"with_json_name" valid:"-,required"` WithoutJSONName string `valid:"-,required"` WithJSONOmit string `json:"with_other_json_name,omitempty" valid:"-,required"` WithJSONOption string `json:",omitempty" valid:"-,required"` WithEmptyJSONName string `json:"-" valid:"-,required"` } _, err := ValidateStruct(val) if err == nil { t.Error("Expected error but got no error") } if Contains(err.Error(), "WithJSONName") { t.Errorf("Expected error message to contain with_json_name but actual error is: %s", err.Error()) } if Contains(err.Error(), "WithoutJSONName") == false { t.Errorf("Expected error message to contain WithoutJSONName but actual error is: %s", err.Error()) } if Contains(err.Error(), "omitempty") { t.Errorf("Expected error message to not contain ',omitempty' but actual error is: %s", err.Error()) } if !Contains(err.Error(), "WithEmptyJSONName") { t.Errorf("Expected error message to contain WithEmptyJSONName but actual error is: %s", err.Error()) } } func TestValidatorIncludedInError(t *testing.T) { post := Post{ Title: "", Message: "👍", AuthorIP: "xyz", } validatorMap := map[string]string{ "Title": "required", "Message": "ascii", "AuthorIP": "ipv4", } ok, errors := ValidateStruct(post) if ok { t.Errorf("expected validation to fail %v", ok) } for _, e := range errors.(Errors) { casted := e.(Error) if validatorMap[casted.Name] != casted.Validator { t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator) } } // check to make sure that validators with arguments (like length(1|10)) don't include the arguments // in the validator name message := MessageWithSeveralFieldsStruct{ Title: "", Body: "asdfasdfasdfasdfasdf", } validatorMap = map[string]string{ "Title": "length", "Body": "length", } ok, errors = ValidateStruct(message) if ok { t.Errorf("expected validation to fail, %v", ok) } for _, e := range errors.(Errors) { casted := e.(Error) if validatorMap[casted.Name] != casted.Validator { t.Errorf("expected validator for %s to be %s, but was %s", casted.Name, validatorMap[casted.Name], casted.Validator) } } // make sure validators with custom messages don't show up in the validator string type CustomMessage struct { Text string `valid:"length(1|10)~Custom message"` } cs := CustomMessage{Text: "asdfasdfasdfasdf"} ok, errors = ValidateStruct(&cs) if ok { t.Errorf("expected validation to fail, %v", ok) } validator := errors.(Errors)[0].(Error).Validator if validator != "length" { t.Errorf("expected validator for Text to be length, but was %s", validator) } } func TestIsRsaPublicKey(t *testing.T) { var tests = []struct { rsastr string keylen int expected bool }{ {`fubar`, 2048, false}, {`MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuu XwKYLq0DKUE3t/HHsNdowfD9+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9BmMEcI3uoKbeXCbJRI HoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzTUmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZ B7ucimFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUvbQIDAQAB`, 2048, true}, {`MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuu XwKYLq0DKUE3t/HHsNdowfD9+NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9BmMEcI3uoKbeXCbJRI HoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzTUmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZ B7ucimFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUvbQIDAQAB`, 1024, false}, {`-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7 x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuuXwKYLq0DKUE3t/HHsNdowfD9 +NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9 BmMEcI3uoKbeXCbJRIHoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzT UmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZB7uc imFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUv bQIDAQAB -----END PUBLIC KEY-----`, 2048, true}, {`-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvncDCeibmEkabJLmFec7 x9y86RP6dIvkVxxbQoOJo06E+p7tH6vCmiGHKnuuXwKYLq0DKUE3t/HHsNdowfD9 +NH8caLzmXqGBx45/Dzxnwqz0qYq7idK+Qff34qrk/YFoU7498U1Ee7PkKb7/VE9 BmMEcI3uoKbeXCbJRIHoTp8bUXOpNTSUfwUNwJzbm2nsHo2xu6virKtAZLTsJFzT UmRd11MrWCvj59lWzt1/eIMN+ekjH8aXeLOOl54CL+kWp48C+V9BchyKCShZB7uc imFvjHTtuxziXZQRO7HlcsBOa0WwvDJnRnskdyoD31s4F4jpKEYBJNWTo63v6lUv bQIDAQAB -----END PUBLIC KEY-----`, 4096, false}, } for i, test := range tests { actual := IsRsaPublicKey(test.rsastr, test.keylen) if actual != test.expected { t.Errorf("Expected TestIsRsaPublicKey(%d, %d) to be %v, got %v", i, test.keylen, test.expected, actual) } } }