3041 lines
77 KiB
Go
3041 lines
77 KiB
Go
|
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)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|