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}, } 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) } } } 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 } 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"` } func TestValidateNegationStruct(t *testing.T) { var tests = []struct { param NegationStruct expected bool }{ {NegationStruct{"a1", "11"}, true}, {NegationStruct{"*****@*****.**", "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 TestValidateStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {User{"John", "*****@*****.**", "123G#678", 20, &Address{"Street", "123456"}, []Address{Address{"Street", "123456"}, Address{"Street", "123456"}}}, false}, {User{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {User{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {UserValid{"John", "*****@*****.**", "123G#678", 20, &Address{"Street", "123456"}, []Address{Address{"Street", "123456"}, Address{"Street", "123456"}}}, true}, {UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {UserValid{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {nil, true}, {User{"John", "*****@*****.**", "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{Address{"Street", "123456"}, Address{"Street", "123456"}}, Address{"Street", "123456"}, map[string]Address{"address": Address{"Street", "123456"}}}) if result != true { t.Log("Case ", 6, ": expected ", true, " when result is ", result) t.Error(err) t.FailNow() } } 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 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}, } 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 TestByteLegnth(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}, } 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) } } } 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 } 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 Post struct { Title string `valid:"alpha,required"` Message string `valid:"ascii"` AuthorIP string `valid:"ipv4"` } func TestValidateNegationStruct(t *testing.T) { var tests = []struct { param NegationStruct expected bool }{ {NegationStruct{"a1", "11"}, true}, {NegationStruct{"*****@*****.**", "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 TestValidateStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {User{"John", "*****@*****.**", "123G#678", 20, &Address{"Street", "123456"}, []Address{Address{"Street", "123456"}, Address{"Street", "123456"}}}, false}, {User{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {User{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {UserValid{"John", "*****@*****.**", "123G#678", 20, &Address{"Street", "123456"}, []Address{Address{"Street", "123456"}, Address{"Street", "123456"}}}, true}, {UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {UserValid{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {nil, true}, {User{"John", "*****@*****.**", "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{Address{"Street", "123456"}, Address{"Street", "123456"}}, Address{"Street", "123456"}, map[string]Address{"address": Address{"Street", "123456"}}}) if result != true { t.Log("Case ", 6, ": expected ", true, " when result is ", result) t.Error(err) t.FailNow() } } 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, }, } 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 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 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}, } 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 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}, } 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 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) } } } 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 } 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 Post struct { Title string `valid:"alpha,required"` Message string `valid:"ascii"` AuthorIP string `valid:"ipv4"` } type MissingValidationDeclationStruct 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"` } func TestValidateMissingValidationDeclationStruct(t *testing.T) { var tests = []struct { param MissingValidationDeclationStruct expected bool }{ {MissingValidationDeclationStruct{}, false}, {MissingValidationDeclationStruct{Name: "TEST", Email: "*****@*****.**"}, 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: "*****@*****.**"}, 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: "*****@*****.**"}, 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) } type CustomByteArray [6]byte type StructWithCustomByteArray struct { ID CustomByteArray `valid:"customByteArrayValidator"` Email string `valid:"email"` } func TestStructWithCustomByteArray(t *testing.T) { // add our custom byte array validator that fails when the byte array is pristine (all zeroes) CustomTypeTagMap["customByteArrayValidator"] = CustomTypeValidator(func(i interface{}) bool { 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 }) testCustomByteArray := CustomByteArray{'1', '2', '3', '4', '5', '6'} var tests = []struct { param StructWithCustomByteArray expected bool }{ {StructWithCustomByteArray{}, false}, {StructWithCustomByteArray{Email: "*****@*****.**"}, false}, {StructWithCustomByteArray{ID: testCustomByteArray, Email: "*****@*****.**"}, 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 TestValidateNegationStruct(t *testing.T) { var tests = []struct { param NegationStruct expected bool }{ {NegationStruct{"a1", "11"}, true}, {NegationStruct{"*****@*****.**", "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 TestValidateStruct(t *testing.T) { var tests = []struct { param interface{} expected bool }{ {User{"John", "*****@*****.**", "123G#678", 20, &Address{"Street", "123456"}, []Address{Address{"Street", "123456"}, Address{"Street", "123456"}}}, false}, {User{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {User{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {UserValid{"John", "*****@*****.**", "123G#678", 20, &Address{"Street", "123456"}, []Address{Address{"Street", "123456"}, Address{"Street", "123456"}}}, true}, {UserValid{"John", "john!yahoo.com", "12345678", 20, &Address{"Street", "ABC456D89"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {UserValid{"John", "", "12345", 0, &Address{"Street", "123456789"}, []Address{Address{"Street", "ABC456D89"}, Address{"Street", "123456"}}}, false}, {nil, true}, {User{"John", "*****@*****.**", "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{Address{"Street", "123456"}, Address{"Street", "123456"}}, Address{"Street", "123456"}, map[string]Address{"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 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, }, } 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) } } } 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) }