...

Source file src/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule/parse_test.go

Documentation: github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule

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

View as plain text