...

Source file src/github.com/emicklei/proto/parser_test.go

Documentation: github.com/emicklei/proto

     1  // Copyright (c) 2017 Ernest Micklei
     2  //
     3  // MIT License
     4  //
     5  // Permission is hereby granted, free of charge, to any person obtaining
     6  // a copy of this software and associated documentation files (the
     7  // "Software"), to deal in the Software without restriction, including
     8  // without limitation the rights to use, copy, modify, merge, publish,
     9  // distribute, sublicense, and/or sell copies of the Software, and to
    10  // permit persons to whom the Software is furnished to do so, subject to
    11  // the following conditions:
    12  //
    13  // The above copyright notice and this permission notice shall be
    14  // included in all copies or substantial portions of the Software.
    15  //
    16  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    17  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    18  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    19  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    20  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    21  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    22  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    23  
    24  package proto
    25  
    26  import (
    27  	"strings"
    28  	"testing"
    29  )
    30  
    31  func TestParseComment(t *testing.T) {
    32  	proto := `
    33      // first
    34  	// second
    35  
    36      /*
    37  	ctyle
    38  	multi
    39  	line
    40      */
    41  
    42      // cpp style single line //
    43  
    44  	message test{}
    45  	`
    46  	p := newParserOn(proto)
    47  	pr, err := p.Parse()
    48  	if err != nil {
    49  		t.Fatal(err)
    50  	}
    51  
    52  	if got, want := len(collect(pr).Comments()), 3; got != want {
    53  		t.Errorf("got [%v] want [%v]", got, want)
    54  	}
    55  }
    56  
    57  func newParserOn(def string) *Parser {
    58  	p := NewParser(strings.NewReader(def))
    59  	p.debug = true
    60  	return p
    61  }
    62  
    63  func TestScanIgnoreWhitespace_Digits(t *testing.T) {
    64  	p := newParserOn(" 1234 ")
    65  	_, _, lit := p.next()
    66  	if got, want := lit, "1234"; got != want {
    67  		t.Errorf("got [%v] want [%v]", got, want)
    68  	}
    69  }
    70  
    71  func TestScanIgnoreWhitespace_Minus(t *testing.T) {
    72  	p := newParserOn(" -1234")
    73  	_, _, lit := p.next()
    74  	if got, want := lit, "-"; got != want {
    75  		t.Errorf("got [%v] want [%v]", got, want)
    76  	}
    77  }
    78  
    79  func TestNextIdentifier(t *testing.T) {
    80  	ident := " aap.noot.mies "
    81  	p := newParserOn(ident)
    82  	_, tok, lit := p.nextIdentifier()
    83  	if got, want := tok, tIDENT; got != want {
    84  		t.Errorf("got [%v] want [%v]", got, want)
    85  	}
    86  	if got, want := lit, strings.TrimSpace(ident); got != want {
    87  		t.Errorf("got [%v] want [%v]", got, want)
    88  	}
    89  }
    90  
    91  func TestNextIdentifierWithKeyword(t *testing.T) {
    92  	ident := " aap.rpc.mies.enum ="
    93  	p := newParserOn(ident)
    94  	_, tok, lit := p.nextIdentifier()
    95  	if got, want := tok, tIDENT; got != want {
    96  		t.Errorf("got [%v] want [%v]", got, want)
    97  	}
    98  	if got, want := lit, "aap.rpc.mies.enum"; got != want {
    99  		t.Errorf("got [%v] want [%v]", got, want)
   100  	}
   101  	_, tok, _ = p.next()
   102  	if got, want := tok, tEQUALS; got != want {
   103  		t.Errorf("got [%v] want [%v]", got, want)
   104  	}
   105  }
   106  
   107  func TestNextTypeNameWithLeadingKeyword(t *testing.T) {
   108  	ident := " service.me.now"
   109  	p := newParserOn(ident)
   110  	_, tok, lit := p.nextTypeName()
   111  	if got, want := tok, tIDENT; got != want {
   112  		t.Errorf("got [%v] want [%v]", got, want)
   113  	}
   114  	if got, want := lit, "service.me.now"; got != want {
   115  		t.Errorf("got [%v] want [%v]", got, want)
   116  	}
   117  }
   118  
   119  func TestNextIdentifierNoIdent(t *testing.T) {
   120  	ident := "("
   121  	p := newParserOn(ident)
   122  	_, tok, lit := p.nextIdentifier()
   123  	if got, want := tok, tLEFTPAREN; got != want {
   124  		t.Errorf("got [%v] want [%v]", got, want)
   125  	}
   126  	if got, want := lit, "("; got != want {
   127  		t.Errorf("got [%v] want [%v]", got, want)
   128  	}
   129  }
   130  
   131  // https://github.com/google/protobuf/issues/4726
   132  func TestProtobufIssue4726(t *testing.T) {
   133  	src := `syntax = "proto3";
   134  
   135  	service SomeService {
   136  		rpc SomeMethod (Whatever) returns (Whatever) {
   137  			option (google.api.http) = {
   138  				delete : "/some/url"
   139  				additional_bindings {
   140  					delete: "/another/url"
   141  				}
   142  			};
   143  		}
   144  	}`
   145  	p := newParserOn(src)
   146  	_, err := p.Parse()
   147  	if err != nil {
   148  		t.Error(err)
   149  	}
   150  }
   151  
   152  func TestProtoIssue92(t *testing.T) {
   153  	src := `syntax = "proto3";
   154  
   155  package test;
   156  
   157  message Foo {
   158    .game.Resource one = 1 [deprecated = true];
   159    repeated .game.sub.Resource two = 2;
   160    map<string, .game.Resource> three = 3;
   161  }`
   162  	p := newParserOn(src)
   163  	_, err := p.Parse()
   164  	if err != nil {
   165  		t.Error(err)
   166  	}
   167  }
   168  
   169  func TestParseSingleQuotesStrings(t *testing.T) {
   170  	p := newParserOn(` 'bohemian','' `)
   171  	_, _, lit := p.next()
   172  	if got, want := lit, "'bohemian'"; got != want {
   173  		t.Errorf("got [%v] want [%v]", got, want)
   174  	}
   175  	_, tok, _ := p.next()
   176  	if got, want := tok, tCOMMA; got != want {
   177  		t.Errorf("got [%v] want [%v]", got, want)
   178  	}
   179  	_, _, lit = p.next()
   180  	if got, want := lit, "''"; got != want {
   181  		t.Errorf("got [%v] want [%v]", got, want)
   182  	}
   183  }
   184  
   185  func TestProtoIssue132(t *testing.T) {
   186  	src := `syntax = "proto3";
   187  package tutorial;
   188  message Person {
   189    string name = 1;
   190    int32 id = 0x2;  // Unique ID number for this person.
   191    string email = 0X3; // parser.Parse err <input>:8:18: found "=" but expected [field sequence number]
   192  }`
   193  	p := newParserOn(src)
   194  	_, err := p.Parse()
   195  	if err != nil {
   196  		t.Error(err)
   197  	}
   198  }
   199  
   200  func TestReservedNegativeRanges(t *testing.T) {
   201  	r := new(Reserved)
   202  	p := newParserOn(`reserved -1;`)
   203  	_, tok, _ := p.next()
   204  	if tRESERVED != tok {
   205  		t.Fail()
   206  	}
   207  	err := r.parse(p)
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  	if got, want := r.Ranges[0].SourceRepresentation(), "-1"; got != want {
   212  		t.Fatalf("got [%v] want [%v]", got, want) // reserved_test.go:59: got [1] want [-1]
   213  	}
   214  }
   215  
   216  func TestParseNegativeEnum(t *testing.T) {
   217  	const def = `
   218  syntax = "proto3";
   219  package example;
   220  
   221  enum Value {
   222    ZERO = 0;
   223    reserved -2, -1;
   224  }`
   225  
   226  	p := NewParser(strings.NewReader(def))
   227  	_, err := p.Parse()
   228  	if err != nil {
   229  		t.Fatal(err) // <input>:7:16: found "-" but expected [range integer]
   230  	}
   231  }
   232  

View as plain text