github.com/gofiber/fiber/v2@v2.47.0/path_testcases_test.go (about)

     1  // ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
     2  // 📝 Github Repository: https://github.com/gofiber/fiber
     3  // 📌 API Documentation: https://docs.gofiber.io
     4  
     5  package fiber
     6  
     7  import (
     8  	"strings"
     9  )
    10  
    11  type routeTestCase struct {
    12  	url          string
    13  	match        bool
    14  	params       []string
    15  	partialCheck bool
    16  }
    17  
    18  type routeCaseCollection struct {
    19  	pattern   string
    20  	testCases []routeTestCase
    21  }
    22  
    23  var (
    24  	benchmarkCases []routeCaseCollection
    25  	routeTestCases []routeCaseCollection
    26  )
    27  
    28  func init() {
    29  	// smaller list for benchmark cases
    30  	benchmarkCases = []routeCaseCollection{
    31  		{
    32  			pattern: "/api/v1/const",
    33  			testCases: []routeTestCase{
    34  				{url: "/api/v1/const", params: []string{}, match: true},
    35  				{url: "/api/v1", params: nil, match: false},
    36  				{url: "/api/v1/", params: nil, match: false},
    37  				{url: "/api/v1/something", params: nil, match: false},
    38  			},
    39  		},
    40  		{
    41  			pattern: "/api/:param/fixedEnd",
    42  			testCases: []routeTestCase{
    43  				{url: "/api/abc/fixedEnd", params: []string{"abc"}, match: true},
    44  				{url: "/api/abc/def/fixedEnd", params: nil, match: false},
    45  			},
    46  		},
    47  		{
    48  			pattern: "/api/v1/:param/*",
    49  			testCases: []routeTestCase{
    50  				{url: "/api/v1/entity", params: []string{"entity", ""}, match: true},
    51  				{url: "/api/v1/entity/", params: []string{"entity", ""}, match: true},
    52  				{url: "/api/v1/entity/1", params: []string{"entity", "1"}, match: true},
    53  				{url: "/api/v", params: nil, match: false},
    54  				{url: "/api/v2", params: nil, match: false},
    55  				{url: "/api/v1/", params: nil, match: false},
    56  			},
    57  		},
    58  	}
    59  
    60  	// combine benchmark cases and other cases
    61  	routeTestCases = benchmarkCases
    62  	routeTestCases = append(
    63  		routeTestCases,
    64  		[]routeCaseCollection{
    65  			{
    66  				pattern: "/api/v1/:param/+",
    67  				testCases: []routeTestCase{
    68  					{url: "/api/v1/entity", params: nil, match: false},
    69  					{url: "/api/v1/entity/", params: nil, match: false},
    70  					{url: "/api/v1/entity/1", params: []string{"entity", "1"}, match: true},
    71  					{url: "/api/v", params: nil, match: false},
    72  					{url: "/api/v2", params: nil, match: false},
    73  					{url: "/api/v1/", params: nil, match: false},
    74  				},
    75  			},
    76  			{
    77  				pattern: "/api/v1/:param?",
    78  				testCases: []routeTestCase{
    79  					{url: "/api/v1", params: []string{""}, match: true},
    80  					{url: "/api/v1/", params: []string{""}, match: true},
    81  					{url: "/api/v1/optional", params: []string{"optional"}, match: true},
    82  					{url: "/api/v", params: nil, match: false},
    83  					{url: "/api/v2", params: nil, match: false},
    84  					{url: "/api/xyz", params: nil, match: false},
    85  				},
    86  			},
    87  			{
    88  				pattern: "/v1/some/resource/name\\:customVerb",
    89  				testCases: []routeTestCase{
    90  					{url: "/v1/some/resource/name:customVerb", params: nil, match: true},
    91  					{url: "/v1/some/resource/name:test", params: nil, match: false},
    92  				},
    93  			},
    94  			{
    95  				pattern: "/v1/some/resource/:name\\:customVerb",
    96  				testCases: []routeTestCase{
    97  					{url: "/v1/some/resource/test:customVerb", params: []string{"test"}, match: true},
    98  					{url: "/v1/some/resource/test:test", params: nil, match: false},
    99  				},
   100  			},
   101  			{
   102  				pattern: "/v1/some/resource/name\\\\:customVerb?\\?/:param/*",
   103  				testCases: []routeTestCase{
   104  					{url: "/v1/some/resource/name:customVerb??/test/optionalWildCard/character", params: []string{"test", "optionalWildCard/character"}, match: true},
   105  					{url: "/v1/some/resource/name:customVerb??/test", params: []string{"test", ""}, match: true},
   106  				},
   107  			},
   108  			{
   109  				pattern: "/api/v1/*",
   110  				testCases: []routeTestCase{
   111  					{url: "/api/v1", params: []string{""}, match: true},
   112  					{url: "/api/v1/", params: []string{""}, match: true},
   113  					{url: "/api/v1/entity", params: []string{"entity"}, match: true},
   114  					{url: "/api/v1/entity/1/2", params: []string{"entity/1/2"}, match: true},
   115  					{url: "/api/v1/Entity/1/2", params: []string{"Entity/1/2"}, match: true},
   116  					{url: "/api/v", params: nil, match: false},
   117  					{url: "/api/v2", params: nil, match: false},
   118  					{url: "/api/abc", params: nil, match: false},
   119  				},
   120  			},
   121  			{
   122  				pattern: "/api/v1/:param",
   123  				testCases: []routeTestCase{
   124  					{url: "/api/v1/entity", params: []string{"entity"}, match: true},
   125  					{url: "/api/v1/entity/8728382", params: nil, match: false},
   126  					{url: "/api/v1", params: nil, match: false},
   127  					{url: "/api/v1/", params: nil, match: false},
   128  				},
   129  			},
   130  			{
   131  				pattern: "/api/v1/:param-:param2",
   132  				testCases: []routeTestCase{
   133  					{url: "/api/v1/entity-entity2", params: []string{"entity", "entity2"}, match: true},
   134  					{url: "/api/v1/entity/8728382", params: nil, match: false},
   135  					{url: "/api/v1/entity-8728382", params: []string{"entity", "8728382"}, match: true},
   136  					{url: "/api/v1", params: nil, match: false},
   137  					{url: "/api/v1/", params: nil, match: false},
   138  				},
   139  			},
   140  			{
   141  				pattern: "/api/v1/:filename.:extension",
   142  				testCases: []routeTestCase{
   143  					{url: "/api/v1/test.pdf", params: []string{"test", "pdf"}, match: true},
   144  					{url: "/api/v1/test/pdf", params: nil, match: false},
   145  					{url: "/api/v1/test-pdf", params: nil, match: false},
   146  					{url: "/api/v1/test_pdf", params: nil, match: false},
   147  					{url: "/api/v1", params: nil, match: false},
   148  					{url: "/api/v1/", params: nil, match: false},
   149  				},
   150  			},
   151  			{
   152  				pattern: "/shop/product/::filter/color::color/size::size",
   153  				testCases: []routeTestCase{
   154  					{url: "/shop/product/:test/color:blue/size:xs", params: []string{"test", "blue", "xs"}, match: true},
   155  					{url: "/shop/product/test/color:blue/size:xs", params: nil, match: false},
   156  				},
   157  			},
   158  			{
   159  				pattern: "/::param?",
   160  				testCases: []routeTestCase{
   161  					{url: "/:hello", params: []string{"hello"}, match: true},
   162  					{url: "/:", params: []string{""}, match: true},
   163  					{url: "/", params: nil, match: false},
   164  				},
   165  			},
   166  			// successive parameters, each take one character and the last parameter gets everything
   167  			{
   168  				pattern: "/test:sign:param",
   169  				testCases: []routeTestCase{
   170  					{url: "/test-abc", params: []string{"-", "abc"}, match: true},
   171  					{url: "/test", params: nil, match: false},
   172  				},
   173  			},
   174  			// optional parameters are not greedy
   175  			{
   176  				pattern: "/:param1:param2?:param3",
   177  				testCases: []routeTestCase{
   178  					{url: "/abbbc", params: []string{"a", "b", "bbc"}, match: true},
   179  					// {url: "/ac", testCases: []string{"a", "", "c"}, match: true}, // TODO: fix it
   180  					{url: "/test", params: []string{"t", "e", "st"}, match: true},
   181  				},
   182  			},
   183  			{
   184  				pattern: "/test:optional?:mandatory",
   185  				testCases: []routeTestCase{
   186  					// {url: "/testo", testCases: []string{"", "o"}, match: true}, // TODO: fix it
   187  					{url: "/testoaaa", params: []string{"o", "aaa"}, match: true},
   188  					{url: "/test", params: nil, match: false},
   189  				},
   190  			},
   191  			{
   192  				pattern: "/test:optional?:optional2?",
   193  				testCases: []routeTestCase{
   194  					{url: "/testo", params: []string{"o", ""}, match: true},
   195  					{url: "/testoaaa", params: []string{"o", "aaa"}, match: true},
   196  					{url: "/test", params: []string{"", ""}, match: true},
   197  					{url: "/tes", params: nil, match: false},
   198  				},
   199  			},
   200  			{
   201  				pattern: "/foo:param?bar",
   202  				testCases: []routeTestCase{
   203  					{url: "/foofaselbar", params: []string{"fasel"}, match: true},
   204  					{url: "/foobar", params: []string{""}, match: true},
   205  					{url: "/fooba", params: nil, match: false},
   206  					{url: "/fobar", params: nil, match: false},
   207  				},
   208  			},
   209  			{
   210  				pattern: "/foo*bar",
   211  				testCases: []routeTestCase{
   212  					{url: "/foofaselbar", params: []string{"fasel"}, match: true},
   213  					{url: "/foobar", params: []string{""}, match: true},
   214  					{url: "/", params: nil, match: false},
   215  				},
   216  			},
   217  			{
   218  				pattern: "/foo+bar",
   219  				testCases: []routeTestCase{
   220  					{url: "/foofaselbar", params: []string{"fasel"}, match: true},
   221  					{url: "/foobar", params: nil, match: false},
   222  					{url: "/", params: nil, match: false},
   223  				},
   224  			},
   225  			{
   226  				pattern: "/a*cde*g/",
   227  				testCases: []routeTestCase{
   228  					{url: "/abbbcdefffg", params: []string{"bbb", "fff"}, match: true},
   229  					{url: "/acdeg", params: []string{"", ""}, match: true},
   230  					{url: "/", params: nil, match: false},
   231  				},
   232  			},
   233  			{
   234  				pattern: "/*v1*/proxy",
   235  				testCases: []routeTestCase{
   236  					{url: "/customer/v1/cart/proxy", params: []string{"customer/", "/cart"}, match: true},
   237  					{url: "/v1/proxy", params: []string{"", ""}, match: true},
   238  					{url: "/v1/", params: nil, match: false},
   239  				},
   240  			},
   241  			// successive wildcard -> first wildcard is greedy
   242  			{
   243  				pattern: "/foo***bar",
   244  				testCases: []routeTestCase{
   245  					{url: "/foo*abar", params: []string{"*a", "", ""}, match: true},
   246  					{url: "/foo*bar", params: []string{"*", "", ""}, match: true},
   247  					{url: "/foobar", params: []string{"", "", ""}, match: true},
   248  					{url: "/fooba", params: nil, match: false},
   249  				},
   250  			},
   251  			// chars in front of an parameter
   252  			{
   253  				pattern: "/name::name",
   254  				testCases: []routeTestCase{
   255  					{url: "/name:john", params: []string{"john"}, match: true},
   256  				},
   257  			},
   258  			{
   259  				pattern: "/@:name",
   260  				testCases: []routeTestCase{
   261  					{url: "/@john", params: []string{"john"}, match: true},
   262  				},
   263  			},
   264  			{
   265  				pattern: "/-:name",
   266  				testCases: []routeTestCase{
   267  					{url: "/-john", params: []string{"john"}, match: true},
   268  				},
   269  			},
   270  			{
   271  				pattern: "/.:name",
   272  				testCases: []routeTestCase{
   273  					{url: "/.john", params: []string{"john"}, match: true},
   274  				},
   275  			},
   276  			{
   277  				pattern: "/api/v1/:param/abc/*",
   278  				testCases: []routeTestCase{
   279  					{url: "/api/v1/well/abc/wildcard", params: []string{"well", "wildcard"}, match: true},
   280  					{url: "/api/v1/well/abc/", params: []string{"well", ""}, match: true},
   281  					{url: "/api/v1/well/abc", params: []string{"well", ""}, match: true},
   282  					{url: "/api/v1/well/ttt", params: nil, match: false},
   283  				},
   284  			},
   285  			{
   286  				pattern: "/api/:day/:month?/:year?",
   287  				testCases: []routeTestCase{
   288  					{url: "/api/1", params: []string{"1", "", ""}, match: true},
   289  					{url: "/api/1/", params: []string{"1", "", ""}, match: true},
   290  					{url: "/api/1//", params: []string{"1", "", ""}, match: true},
   291  					{url: "/api/1/-/", params: []string{"1", "-", ""}, match: true},
   292  					{url: "/api/1-", params: []string{"1-", "", ""}, match: true},
   293  					{url: "/api/1.", params: []string{"1.", "", ""}, match: true},
   294  					{url: "/api/1/2", params: []string{"1", "2", ""}, match: true},
   295  					{url: "/api/1/2/3", params: []string{"1", "2", "3"}, match: true},
   296  					{url: "/api/", params: nil, match: false},
   297  				},
   298  			},
   299  			{
   300  				pattern: "/api/:day.:month?.:year?",
   301  				testCases: []routeTestCase{
   302  					{url: "/api/1", params: nil, match: false},
   303  					{url: "/api/1/", params: nil, match: false},
   304  					{url: "/api/1.", params: nil, match: false},
   305  					{url: "/api/1..", params: []string{"1", "", ""}, match: true},
   306  					{url: "/api/1.2", params: nil, match: false},
   307  					{url: "/api/1.2.", params: []string{"1", "2", ""}, match: true},
   308  					{url: "/api/1.2.3", params: []string{"1", "2", "3"}, match: true},
   309  					{url: "/api/", params: nil, match: false},
   310  				},
   311  			},
   312  			{
   313  				pattern: "/api/:day-:month?-:year?",
   314  				testCases: []routeTestCase{
   315  					{url: "/api/1", params: nil, match: false},
   316  					{url: "/api/1/", params: nil, match: false},
   317  					{url: "/api/1-", params: nil, match: false},
   318  					{url: "/api/1--", params: []string{"1", "", ""}, match: true},
   319  					{url: "/api/1-/", params: nil, match: false},
   320  					// {url: "/api/1-/-", testCases: nil, match: false}, // TODO: fix this part
   321  					{url: "/api/1-2", params: nil, match: false},
   322  					{url: "/api/1-2-", params: []string{"1", "2", ""}, match: true},
   323  					{url: "/api/1-2-3", params: []string{"1", "2", "3"}, match: true},
   324  					{url: "/api/", params: nil, match: false},
   325  				},
   326  			},
   327  			{
   328  				pattern: "/api/*",
   329  				testCases: []routeTestCase{
   330  					{url: "/api/", params: []string{""}, match: true},
   331  					{url: "/api/joker", params: []string{"joker"}, match: true},
   332  					{url: "/api", params: []string{""}, match: true},
   333  					{url: "/api/v1/entity", params: []string{"v1/entity"}, match: true},
   334  					{url: "/api2/v1/entity", params: nil, match: false},
   335  					{url: "/api_ignore/v1/entity", params: nil, match: false},
   336  				},
   337  			},
   338  			{
   339  				pattern: "/partialCheck/foo/bar/:param",
   340  				testCases: []routeTestCase{
   341  					{url: "/partialCheck/foo/bar/test", params: []string{"test"}, match: true, partialCheck: true},
   342  					{url: "/partialCheck/foo/bar/test/test2", params: []string{"test"}, match: true, partialCheck: true},
   343  					{url: "/partialCheck/foo/bar", params: nil, match: false, partialCheck: true},
   344  					{url: "/partiaFoo", params: nil, match: false, partialCheck: true},
   345  				},
   346  			},
   347  			{
   348  				pattern: "/",
   349  				testCases: []routeTestCase{
   350  					{url: "/api", params: nil, match: false},
   351  					{url: "", params: []string{}, match: true},
   352  					{url: "/", params: []string{}, match: true},
   353  				},
   354  			},
   355  			{
   356  				pattern: "/config/abc.json",
   357  				testCases: []routeTestCase{
   358  					{url: "/config/abc.json", params: []string{}, match: true},
   359  					{url: "config/abc.json", params: nil, match: false},
   360  					{url: "/config/efg.json", params: nil, match: false},
   361  					{url: "/config", params: nil, match: false},
   362  				},
   363  			},
   364  			{
   365  				pattern: "/config/*.json",
   366  				testCases: []routeTestCase{
   367  					{url: "/config/abc.json", params: []string{"abc"}, match: true},
   368  					{url: "/config/efg.json", params: []string{"efg"}, match: true},
   369  					{url: "/config/.json", params: []string{""}, match: true},
   370  					{url: "/config/efg.csv", params: nil, match: false},
   371  					{url: "config/abc.json", params: nil, match: false},
   372  					{url: "/config", params: nil, match: false},
   373  				},
   374  			},
   375  			{
   376  				pattern: "/config/+.json",
   377  				testCases: []routeTestCase{
   378  					{url: "/config/abc.json", params: []string{"abc"}, match: true},
   379  					{url: "/config/.json", params: nil, match: false},
   380  					{url: "/config/efg.json", params: []string{"efg"}, match: true},
   381  					{url: "/config/efg.csv", params: nil, match: false},
   382  					{url: "config/abc.json", params: nil, match: false},
   383  					{url: "/config", params: nil, match: false},
   384  				},
   385  			},
   386  			{
   387  				pattern: "/xyz",
   388  				testCases: []routeTestCase{
   389  					{url: "xyz", params: nil, match: false},
   390  					{url: "xyz/", params: nil, match: false},
   391  				},
   392  			},
   393  			{
   394  				pattern: "/api/*/:param?",
   395  				testCases: []routeTestCase{
   396  					{url: "/api/", params: []string{"", ""}, match: true},
   397  					{url: "/api/joker", params: []string{"joker", ""}, match: true},
   398  					{url: "/api/joker/batman", params: []string{"joker", "batman"}, match: true},
   399  					{url: "/api/joker//batman", params: []string{"joker/", "batman"}, match: true},
   400  					{url: "/api/joker/batman/robin", params: []string{"joker/batman", "robin"}, match: true},
   401  					{url: "/api/joker/batman/robin/1", params: []string{"joker/batman/robin", "1"}, match: true},
   402  					{url: "/api/joker/batman/robin/1/", params: []string{"joker/batman/robin/1", ""}, match: true},
   403  					{url: "/api/joker-batman/robin/1", params: []string{"joker-batman/robin", "1"}, match: true},
   404  					{url: "/api/joker-batman-robin/1", params: []string{"joker-batman-robin", "1"}, match: true},
   405  					{url: "/api/joker-batman-robin-1", params: []string{"joker-batman-robin-1", ""}, match: true},
   406  					{url: "/api", params: []string{"", ""}, match: true},
   407  				},
   408  			},
   409  			{
   410  				pattern: "/api/*/:param",
   411  				testCases: []routeTestCase{
   412  					{url: "/api/test/abc", params: []string{"test", "abc"}, match: true},
   413  					{url: "/api/joker/batman", params: []string{"joker", "batman"}, match: true},
   414  					{url: "/api/joker/batman/robin", params: []string{"joker/batman", "robin"}, match: true},
   415  					{url: "/api/joker/batman/robin/1", params: []string{"joker/batman/robin", "1"}, match: true},
   416  					{url: "/api/joker/batman-robin/1", params: []string{"joker/batman-robin", "1"}, match: true},
   417  					{url: "/api/joker-batman-robin-1", params: nil, match: false},
   418  					{url: "/api", params: nil, match: false},
   419  				},
   420  			},
   421  			{
   422  				pattern: "/api/+/:param",
   423  				testCases: []routeTestCase{
   424  					{url: "/api/test/abc", params: []string{"test", "abc"}, match: true},
   425  					{url: "/api/joker/batman/robin/1", params: []string{"joker/batman/robin", "1"}, match: true},
   426  					{url: "/api/joker", params: nil, match: false},
   427  					{url: "/api", params: nil, match: false},
   428  				},
   429  			},
   430  			{
   431  				pattern: "/api/*/:param/:param2",
   432  				testCases: []routeTestCase{
   433  					{url: "/api/test/abc/1", params: []string{"test", "abc", "1"}, match: true},
   434  					{url: "/api/joker/batman", params: nil, match: false},
   435  					{url: "/api/joker/batman-robin/1", params: []string{"joker", "batman-robin", "1"}, match: true},
   436  					{url: "/api/joker-batman-robin-1", params: nil, match: false},
   437  					{url: "/api/test/abc", params: nil, match: false},
   438  					{url: "/api/joker/batman/robin", params: []string{"joker", "batman", "robin"}, match: true},
   439  					{url: "/api/joker/batman/robin/1", params: []string{"joker/batman", "robin", "1"}, match: true},
   440  					{url: "/api/joker/batman/robin/1/2", params: []string{"joker/batman/robin", "1", "2"}, match: true},
   441  					{url: "/api", params: nil, match: false},
   442  					{url: "/api/:test", params: nil, match: false},
   443  				},
   444  			},
   445  			{
   446  				pattern: "/api/v1/:param<int>",
   447  				testCases: []routeTestCase{
   448  					{url: "/api/v1/entity", params: nil, match: false},
   449  					{url: "/api/v1/8728382", params: []string{"8728382"}, match: true},
   450  					{url: "/api/v1/true", params: nil, match: false},
   451  				},
   452  			},
   453  			{
   454  				pattern: "/api/v1/:param<bool>",
   455  				testCases: []routeTestCase{
   456  					{url: "/api/v1/entity", params: nil, match: false},
   457  					{url: "/api/v1/8728382", params: nil, match: false},
   458  					{url: "/api/v1/true", params: []string{"true"}, match: true},
   459  				},
   460  			},
   461  			{
   462  				pattern: "/api/v1/:param<float>",
   463  				testCases: []routeTestCase{
   464  					{url: "/api/v1/entity", params: nil, match: false},
   465  					{url: "/api/v1/8728382", params: []string{"8728382"}, match: true},
   466  					{url: "/api/v1/8728382.5", params: []string{"8728382.5"}, match: true},
   467  					{url: "/api/v1/true", params: nil, match: false},
   468  				},
   469  			},
   470  			{
   471  				pattern: "/api/v1/:param<alpha>",
   472  				testCases: []routeTestCase{
   473  					{url: "/api/v1/entity", params: []string{"entity"}, match: true},
   474  					{url: "/api/v1/#!?", params: nil, match: false},
   475  					{url: "/api/v1/8728382", params: nil, match: false},
   476  				},
   477  			},
   478  			{
   479  				pattern: "/api/v1/:param<guid>",
   480  				testCases: []routeTestCase{
   481  					{url: "/api/v1/entity", params: nil, match: false},
   482  					{url: "/api/v1/8728382", params: nil, match: false},
   483  					{url: "/api/v1/f0fa66cc-d22e-445b-866d-1d76e776371d", params: []string{"f0fa66cc-d22e-445b-866d-1d76e776371d"}, match: true},
   484  				},
   485  			},
   486  			{
   487  				pattern: "/api/v1/:param<minLen>",
   488  				testCases: []routeTestCase{
   489  					{url: "/api/v1/entity", params: nil, match: false},
   490  					{url: "/api/v1/8728382", params: nil, match: false},
   491  				},
   492  			},
   493  			{
   494  				pattern: "/api/v1/:param<minLen(5)>",
   495  				testCases: []routeTestCase{
   496  					{url: "/api/v1/entity", params: []string{"entity"}, match: true},
   497  					{url: "/api/v1/ent", params: nil, match: false},
   498  					{url: "/api/v1/8728382", params: []string{"8728382"}, match: true},
   499  					{url: "/api/v1/123", params: nil, match: false},
   500  					{url: "/api/v1/12345", params: []string{"12345"}, match: true},
   501  				},
   502  			},
   503  			{
   504  				pattern: "/api/v1/:param<maxLen(5)>",
   505  				testCases: []routeTestCase{
   506  					{url: "/api/v1/entity", params: nil, match: false},
   507  					{url: "/api/v1/ent", params: []string{"ent"}, match: true},
   508  					{url: "/api/v1/8728382", params: nil, match: false},
   509  					{url: "/api/v1/123", params: []string{"123"}, match: true},
   510  					{url: "/api/v1/12345", params: []string{"12345"}, match: true},
   511  				},
   512  			},
   513  			{
   514  				pattern: "/api/v1/:param<len(5)>",
   515  				testCases: []routeTestCase{
   516  					{url: "/api/v1/ent", params: nil, match: false},
   517  					{url: "/api/v1/123", params: nil, match: false},
   518  					{url: "/api/v1/12345", params: []string{"12345"}, match: true},
   519  				},
   520  			},
   521  			{
   522  				pattern: "/api/v1/:param<betweenLen(1)>",
   523  				testCases: []routeTestCase{
   524  					{url: "/api/v1/entity", params: nil, match: false},
   525  					{url: "/api/v1/ent", params: nil, match: false},
   526  				},
   527  			},
   528  			{
   529  				pattern: "/api/v1/:param<betweenLen(2,5)>",
   530  				testCases: []routeTestCase{
   531  					{url: "/api/v1/e", params: nil, match: false},
   532  					{url: "/api/v1/en", params: []string{"en"}, match: true},
   533  					{url: "/api/v1/8728382", params: nil, match: false},
   534  					{url: "/api/v1/123", params: []string{"123"}, match: true},
   535  					{url: "/api/v1/12345", params: []string{"12345"}, match: true},
   536  				},
   537  			},
   538  			{
   539  				pattern: "/api/v1/:param<betweenLen(2,5)>",
   540  				testCases: []routeTestCase{
   541  					{url: "/api/v1/e", params: nil, match: false},
   542  					{url: "/api/v1/en", params: []string{"en"}, match: true},
   543  					{url: "/api/v1/8728382", params: nil, match: false},
   544  					{url: "/api/v1/123", params: []string{"123"}, match: true},
   545  					{url: "/api/v1/12345", params: []string{"12345"}, match: true},
   546  				},
   547  			},
   548  			{
   549  				pattern: "/api/v1/:param<min(5)>",
   550  				testCases: []routeTestCase{
   551  					{url: "/api/v1/ent", params: nil, match: false},
   552  					{url: "/api/v1/1", params: nil, match: false},
   553  					{url: "/api/v1/5", params: []string{"5"}, match: true},
   554  				},
   555  			},
   556  			{
   557  				pattern: "/api/v1/:param<max(5)>",
   558  				testCases: []routeTestCase{
   559  					{url: "/api/v1/ent", params: nil, match: false},
   560  					{url: "/api/v1/1", params: []string{"1"}, match: true},
   561  					{url: "/api/v1/5", params: []string{"5"}, match: true},
   562  					{url: "/api/v1/15", params: nil, match: false},
   563  				},
   564  			},
   565  			{
   566  				pattern: "/api/v1/:param<range(5,10)>",
   567  				testCases: []routeTestCase{
   568  					{url: "/api/v1/ent", params: nil, match: false},
   569  					{url: "/api/v1/9", params: []string{"9"}, match: true},
   570  					{url: "/api/v1/5", params: []string{"5"}, match: true},
   571  					{url: "/api/v1/15", params: nil, match: false},
   572  				},
   573  			},
   574  			{
   575  				pattern: "/api/v1/:param<datetime(2006\\-01\\-02)>",
   576  				testCases: []routeTestCase{
   577  					{url: "/api/v1/entity", params: nil, match: false},
   578  					{url: "/api/v1/8728382", params: nil, match: false},
   579  					{url: "/api/v1/2005-11-01", params: []string{"2005-11-01"}, match: true},
   580  				},
   581  			},
   582  			{
   583  				pattern: "/api/v1/:param<regex(p([a-z]+)ch)>",
   584  				testCases: []routeTestCase{
   585  					{url: "/api/v1/ent", params: nil, match: false},
   586  					{url: "/api/v1/15", params: nil, match: false},
   587  					{url: "/api/v1/peach", params: []string{"peach"}, match: true},
   588  					{url: "/api/v1/p34ch", params: nil, match: false},
   589  				},
   590  			},
   591  			{
   592  				pattern: "/api/v1/:param<regex(^[a-z0-9]([a-z0-9-]{1,61}[a-z0-9])?$)>",
   593  				testCases: []routeTestCase{
   594  					{url: "/api/v1/12", params: nil, match: false},
   595  					{url: "/api/v1/xy", params: nil, match: false},
   596  					{url: "/api/v1/test", params: []string{"test"}, match: true},
   597  					{url: "/api/v1/" + strings.Repeat("a", 64), params: nil, match: false},
   598  				},
   599  			},
   600  			{
   601  				pattern: "/api/v1/:param<regex(\\d{4}-\\d{2}-\\d{2})}>",
   602  				testCases: []routeTestCase{
   603  					{url: "/api/v1/ent", params: nil, match: false},
   604  					{url: "/api/v1/15", params: nil, match: false},
   605  					{url: "/api/v1/2022-08-27", params: []string{"2022-08-27"}, match: true},
   606  					{url: "/api/v1/2022/08-27", params: nil, match: false},
   607  				},
   608  			},
   609  			{
   610  				pattern: "/api/v1/:param<int;bool((>",
   611  				testCases: []routeTestCase{
   612  					{url: "/api/v1/entity", params: nil, match: false},
   613  					{url: "/api/v1/8728382", params: []string{"8728382"}, match: true},
   614  					{url: "/api/v1/true", params: nil, match: false},
   615  				},
   616  			},
   617  			{
   618  				pattern: "/api/v1/:param<int;max(3000)>",
   619  				testCases: []routeTestCase{
   620  					{url: "/api/v1/entity", params: nil, match: false},
   621  					{url: "/api/v1/8728382", params: nil, match: false},
   622  					{url: "/api/v1/123", params: []string{"123"}, match: true},
   623  					{url: "/api/v1/true", params: nil, match: false},
   624  				},
   625  			},
   626  			{
   627  				pattern: "/api/v1/:param<int;maxLen(10)>",
   628  				testCases: []routeTestCase{
   629  					{url: "/api/v1/entity", params: nil, match: false},
   630  					{url: "/api/v1/87283827683", params: nil, match: false},
   631  					{url: "/api/v1/123", params: []string{"123"}, match: true},
   632  					{url: "/api/v1/true", params: nil, match: false},
   633  				},
   634  			},
   635  			{
   636  				pattern: "/api/v1/:param<int;range(10,30)>",
   637  				testCases: []routeTestCase{
   638  					{url: "/api/v1/entity", params: nil, match: false},
   639  					{url: "/api/v1/87283827683", params: nil, match: false},
   640  					{url: "/api/v1/25", params: []string{"25"}, match: true},
   641  					{url: "/api/v1/true", params: nil, match: false},
   642  				},
   643  			},
   644  			{
   645  				pattern: "/api/v1/:param<int\\;range(10,30)>",
   646  				testCases: []routeTestCase{
   647  					{url: "/api/v1/entity", params: []string{"entity"}, match: true},
   648  					{url: "/api/v1/87283827683", params: []string{"87283827683"}, match: true},
   649  					{url: "/api/v1/25", params: []string{"25"}, match: true},
   650  					{url: "/api/v1/true", params: []string{"true"}, match: true},
   651  				},
   652  			},
   653  			{
   654  				pattern: "/api/v1/:param<range(10\\,30,1500)>",
   655  				testCases: []routeTestCase{
   656  					{url: "/api/v1/entity", params: nil, match: false},
   657  					{url: "/api/v1/87283827683", params: nil, match: false},
   658  					{url: "/api/v1/25", params: []string{"25"}, match: true},
   659  					{url: "/api/v1/1200", params: []string{"1200"}, match: true},
   660  					{url: "/api/v1/true", params: nil, match: false},
   661  				},
   662  			},
   663  			{
   664  				pattern: "/api/v1/:lang<len(2)>/videos/:page<range(100,1500)>",
   665  				testCases: []routeTestCase{
   666  					{url: "/api/v1/try/videos/200", params: nil, match: false},
   667  					{url: "/api/v1/tr/videos/1800", params: nil, match: false},
   668  					{url: "/api/v1/tr/videos/100", params: []string{"tr", "100"}, match: true},
   669  					{url: "/api/v1/e/videos/10", params: nil, match: false},
   670  				},
   671  			},
   672  			{
   673  				pattern: "/api/v1/:lang<len(2)>/:page<range(100,1500)>",
   674  				testCases: []routeTestCase{
   675  					{url: "/api/v1/try/200", params: nil, match: false},
   676  					{url: "/api/v1/tr/1800", params: nil, match: false},
   677  					{url: "/api/v1/tr/100", params: []string{"tr", "100"}, match: true},
   678  					{url: "/api/v1/e/10", params: nil, match: false},
   679  				},
   680  			},
   681  			{
   682  				pattern: "/api/v1/:lang/:page<range(100,1500)>",
   683  				testCases: []routeTestCase{
   684  					{url: "/api/v1/try/200", params: []string{"try", "200"}, match: true},
   685  					{url: "/api/v1/tr/1800", params: nil, match: false},
   686  					{url: "/api/v1/tr/100", params: []string{"tr", "100"}, match: true},
   687  					{url: "/api/v1/e/10", params: nil, match: false},
   688  				},
   689  			},
   690  			{
   691  				pattern: "/api/v1/:lang<len(2)>/:page",
   692  				testCases: []routeTestCase{
   693  					{url: "/api/v1/try/200", params: nil, match: false},
   694  					{url: "/api/v1/tr/1800", params: []string{"tr", "1800"}, match: true},
   695  					{url: "/api/v1/tr/100", params: []string{"tr", "100"}, match: true},
   696  					{url: "/api/v1/e/10", params: nil, match: false},
   697  				},
   698  			},
   699  			{
   700  				pattern: "/api/v1/:date<datetime(2006\\-01\\-02)>/:regex<regex(p([a-z]+)ch)>",
   701  				testCases: []routeTestCase{
   702  					{url: "/api/v1/2005-11-01/a", params: nil, match: false},
   703  					{url: "/api/v1/2005-1101/paach", params: nil, match: false},
   704  					{url: "/api/v1/2005-11-01/peach", params: []string{"2005-11-01", "peach"}, match: true},
   705  				},
   706  			},
   707  			{
   708  				pattern: "/api/v1/:param<int>?",
   709  				testCases: []routeTestCase{
   710  					{url: "/api/v1/entity", params: nil, match: false},
   711  					{url: "/api/v1/8728382", params: []string{"8728382"}, match: true},
   712  					{url: "/api/v1/true", params: nil, match: false},
   713  					{url: "/api/v1/", params: []string{""}, match: true},
   714  				},
   715  			},
   716  		}...,
   717  	)
   718  }