github.com/btccom/go-micro/v2@v2.9.3/api/router/util/parse_test.go (about)

     1  package util
     2  
     3  // download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/parse_test.go
     4  
     5  import (
     6  	"flag"
     7  	"fmt"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/btccom/go-micro/v2/logger"
    12  )
    13  
    14  func TestTokenize(t *testing.T) {
    15  	for _, spec := range []struct {
    16  		src    string
    17  		tokens []string
    18  	}{
    19  		{
    20  			src:    "",
    21  			tokens: []string{eof},
    22  		},
    23  		{
    24  			src:    "v1",
    25  			tokens: []string{"v1", eof},
    26  		},
    27  		{
    28  			src:    "v1/b",
    29  			tokens: []string{"v1", "/", "b", eof},
    30  		},
    31  		{
    32  			src:    "v1/endpoint/*",
    33  			tokens: []string{"v1", "/", "endpoint", "/", "*", eof},
    34  		},
    35  		{
    36  			src:    "v1/endpoint/**",
    37  			tokens: []string{"v1", "/", "endpoint", "/", "**", eof},
    38  		},
    39  		{
    40  			src: "v1/b/{bucket_name=*}",
    41  			tokens: []string{
    42  				"v1", "/",
    43  				"b", "/",
    44  				"{", "bucket_name", "=", "*", "}",
    45  				eof,
    46  			},
    47  		},
    48  		{
    49  			src: "v1/b/{bucket_name=buckets/*}",
    50  			tokens: []string{
    51  				"v1", "/",
    52  				"b", "/",
    53  				"{", "bucket_name", "=", "buckets", "/", "*", "}",
    54  				eof,
    55  			},
    56  		},
    57  		{
    58  			src: "v1/b/{bucket_name=buckets/*}/o",
    59  			tokens: []string{
    60  				"v1", "/",
    61  				"b", "/",
    62  				"{", "bucket_name", "=", "buckets", "/", "*", "}", "/",
    63  				"o",
    64  				eof,
    65  			},
    66  		},
    67  		{
    68  			src: "v1/b/{bucket_name=buckets/*}/o/{name}",
    69  			tokens: []string{
    70  				"v1", "/",
    71  				"b", "/",
    72  				"{", "bucket_name", "=", "buckets", "/", "*", "}", "/",
    73  				"o", "/", "{", "name", "}",
    74  				eof,
    75  			},
    76  		},
    77  		{
    78  			src: "v1/a=b&c=d;e=f:g/endpoint.rdf",
    79  			tokens: []string{
    80  				"v1", "/",
    81  				"a=b&c=d;e=f:g", "/",
    82  				"endpoint.rdf",
    83  				eof,
    84  			},
    85  		},
    86  	} {
    87  		tokens, verb := tokenize(spec.src)
    88  		if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) {
    89  			t.Errorf("tokenize(%q) = %q, _; want %q, _", spec.src, got, want)
    90  		}
    91  		if got, want := verb, ""; got != want {
    92  			t.Errorf("tokenize(%q) = _, %q; want _, %q", spec.src, got, want)
    93  		}
    94  
    95  		src := fmt.Sprintf("%s:%s", spec.src, "LOCK")
    96  		tokens, verb = tokenize(src)
    97  		if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) {
    98  			t.Errorf("tokenize(%q) = %q, _; want %q, _", src, got, want)
    99  		}
   100  		if got, want := verb, "LOCK"; got != want {
   101  			t.Errorf("tokenize(%q) = _, %q; want _, %q", src, got, want)
   102  		}
   103  	}
   104  }
   105  
   106  func TestParseSegments(t *testing.T) {
   107  	flag.Set("v", "3")
   108  	for _, spec := range []struct {
   109  		tokens []string
   110  		want   []segment
   111  	}{
   112  		{
   113  			tokens: []string{"v1", eof},
   114  			want: []segment{
   115  				literal("v1"),
   116  			},
   117  		},
   118  		{
   119  			tokens: []string{"/", eof},
   120  			want: []segment{
   121  				wildcard{},
   122  			},
   123  		},
   124  		{
   125  			tokens: []string{"-._~!$&'()*+,;=:@", eof},
   126  			want: []segment{
   127  				literal("-._~!$&'()*+,;=:@"),
   128  			},
   129  		},
   130  		{
   131  			tokens: []string{"%e7%ac%ac%e4%b8%80%e7%89%88", eof},
   132  			want: []segment{
   133  				literal("%e7%ac%ac%e4%b8%80%e7%89%88"),
   134  			},
   135  		},
   136  		{
   137  			tokens: []string{"v1", "/", "*", eof},
   138  			want: []segment{
   139  				literal("v1"),
   140  				wildcard{},
   141  			},
   142  		},
   143  		{
   144  			tokens: []string{"v1", "/", "**", eof},
   145  			want: []segment{
   146  				literal("v1"),
   147  				deepWildcard{},
   148  			},
   149  		},
   150  		{
   151  			tokens: []string{"{", "name", "}", eof},
   152  			want: []segment{
   153  				variable{
   154  					path: "name",
   155  					segments: []segment{
   156  						wildcard{},
   157  					},
   158  				},
   159  			},
   160  		},
   161  		{
   162  			tokens: []string{"{", "name", "=", "*", "}", eof},
   163  			want: []segment{
   164  				variable{
   165  					path: "name",
   166  					segments: []segment{
   167  						wildcard{},
   168  					},
   169  				},
   170  			},
   171  		},
   172  		{
   173  			tokens: []string{"{", "field", ".", "nested", ".", "nested2", "=", "*", "}", eof},
   174  			want: []segment{
   175  				variable{
   176  					path: "field.nested.nested2",
   177  					segments: []segment{
   178  						wildcard{},
   179  					},
   180  				},
   181  			},
   182  		},
   183  		{
   184  			tokens: []string{"{", "name", "=", "a", "/", "b", "/", "*", "}", eof},
   185  			want: []segment{
   186  				variable{
   187  					path: "name",
   188  					segments: []segment{
   189  						literal("a"),
   190  						literal("b"),
   191  						wildcard{},
   192  					},
   193  				},
   194  			},
   195  		},
   196  		{
   197  			tokens: []string{
   198  				"v1", "/",
   199  				"{",
   200  				"name", ".", "nested", ".", "nested2",
   201  				"=",
   202  				"a", "/", "b", "/", "*",
   203  				"}", "/",
   204  				"o", "/",
   205  				"{",
   206  				"another_name",
   207  				"=",
   208  				"a", "/", "b", "/", "*", "/", "c",
   209  				"}", "/",
   210  				"**",
   211  				eof},
   212  			want: []segment{
   213  				literal("v1"),
   214  				variable{
   215  					path: "name.nested.nested2",
   216  					segments: []segment{
   217  						literal("a"),
   218  						literal("b"),
   219  						wildcard{},
   220  					},
   221  				},
   222  				literal("o"),
   223  				variable{
   224  					path: "another_name",
   225  					segments: []segment{
   226  						literal("a"),
   227  						literal("b"),
   228  						wildcard{},
   229  						literal("c"),
   230  					},
   231  				},
   232  				deepWildcard{},
   233  			},
   234  		},
   235  	} {
   236  		p := parser{tokens: spec.tokens}
   237  		segs, err := p.topLevelSegments()
   238  		if err != nil {
   239  			t.Errorf("parser{%q}.segments() failed with %v; want success", spec.tokens, err)
   240  			continue
   241  		}
   242  		if got, want := segs, spec.want; !reflect.DeepEqual(got, want) {
   243  			t.Errorf("parser{%q}.segments() = %#v; want %#v", spec.tokens, got, want)
   244  		}
   245  		if got := p.tokens; len(got) > 0 {
   246  			t.Errorf("p.tokens = %q; want []; spec.tokens=%q", got, spec.tokens)
   247  		}
   248  	}
   249  }
   250  
   251  func TestParseSegmentsWithErrors(t *testing.T) {
   252  	flag.Set("v", "3")
   253  	for _, spec := range []struct {
   254  		tokens []string
   255  	}{
   256  		{
   257  			// double slash
   258  			tokens: []string{"//", eof},
   259  		},
   260  		{
   261  			// invalid literal
   262  			tokens: []string{"a?b", eof},
   263  		},
   264  		{
   265  			// invalid percent-encoding
   266  			tokens: []string{"%", eof},
   267  		},
   268  		{
   269  			// invalid percent-encoding
   270  			tokens: []string{"%2", eof},
   271  		},
   272  		{
   273  			// invalid percent-encoding
   274  			tokens: []string{"a%2z", eof},
   275  		},
   276  		{
   277  			// empty segments
   278  			tokens: []string{eof},
   279  		},
   280  		{
   281  			// unterminated variable
   282  			tokens: []string{"{", "name", eof},
   283  		},
   284  		{
   285  			// unterminated variable
   286  			tokens: []string{"{", "name", "=", eof},
   287  		},
   288  		{
   289  			// unterminated variable
   290  			tokens: []string{"{", "name", "=", "*", eof},
   291  		},
   292  		{
   293  			// empty component in field path
   294  			tokens: []string{"{", "name", ".", "}", eof},
   295  		},
   296  		{
   297  			// empty component in field path
   298  			tokens: []string{"{", "name", ".", ".", "nested", "}", eof},
   299  		},
   300  		{
   301  			// invalid character in identifier
   302  			tokens: []string{"{", "field-name", "}", eof},
   303  		},
   304  		{
   305  			// no slash between segments
   306  			tokens: []string{"v1", "endpoint", eof},
   307  		},
   308  		{
   309  			// no slash between segments
   310  			tokens: []string{"v1", "{", "name", "}", eof},
   311  		},
   312  	} {
   313  		p := parser{tokens: spec.tokens}
   314  		segs, err := p.topLevelSegments()
   315  		if err == nil {
   316  			t.Errorf("parser{%q}.segments() succeeded; want InvalidTemplateError; accepted %#v", spec.tokens, segs)
   317  			continue
   318  		}
   319  		logger.Info(err)
   320  	}
   321  }