github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/validator_test.go (about)

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