1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package proto
25
26 import (
27 "testing"
28 )
29
30 func TestOptionCases(t *testing.T) {
31 for i, each := range []struct {
32 proto string
33 name string
34 strLit string
35 nonStrLit string
36 }{{
37 `option (full).java_package = "com.example.foo";`,
38 "(full).java_package",
39 "com.example.foo",
40 "",
41 }, {
42 `option Bool = true;`,
43 "Bool",
44 "",
45 "true",
46 }, {
47 `option Float = -3.14E1;`,
48 "Float",
49 "",
50 "-3.14E1",
51 }, {
52 `option (foo_options) = { opt1: 123 opt2: "baz" };`,
53 "(foo_options)",
54 "",
55 "",
56 }, {
57 `option foo = []`,
58 "foo",
59 "",
60 "",
61 }, {
62 `option optimize_for = SPEED;`,
63 "optimize_for",
64 "",
65 "SPEED",
66 }, {
67 "option (my.enum.service.is.like).rpc = 1;",
68 "(my.enum.service.is.like).rpc",
69 "",
70 "1",
71 }, {
72 `option (imported.oss.package).action = "literal-double-quotes";`,
73 "(imported.oss.package).action",
74 "literal-double-quotes",
75 "",
76 }, {
77 `option (imported.oss.package).action = "key:\"literal-double-quotes-escaped\"";`,
78 "(imported.oss.package).action",
79 `key:\"literal-double-quotes-escaped\"`,
80 "",
81 }, {
82 `option (imported.oss.package).action = 'literalsinglequotes';`,
83 "(imported.oss.package).action",
84 "literalsinglequotes",
85 "",
86 }, {
87 `option (imported.oss.package).action = 'single-quotes.with/symbols';`,
88 "(imported.oss.package).action",
89 "single-quotes.with/symbols",
90 "",
91 }} {
92 p := newParserOn(each.proto)
93 pr, err := p.Parse()
94 if err != nil {
95 t.Fatal("testcase failed:", i, err)
96 }
97 if got, want := len(pr.Elements), 1; got != want {
98 t.Fatalf("[%d] got [%v] want [%v]", i, got, want)
99 }
100 o := pr.Elements[0].(*Option)
101 if got, want := o.Name, each.name; got != want {
102 t.Errorf("[%d] got [%v] want [%v]", i, got, want)
103 }
104 if len(each.strLit) > 0 {
105 if got, want := o.Constant.Source, each.strLit; got != want {
106 t.Errorf("[%d] got [%v] want [%v]", i, got, want)
107 }
108 }
109 if len(each.nonStrLit) > 0 {
110 if got, want := o.Constant.Source, each.nonStrLit; got != want {
111 t.Errorf("[%d] got [%v] want [%v]", i, got, want)
112 }
113 }
114 if got, want := o.IsEmbedded, false; got != want {
115 t.Errorf("[%d] got [%v] want [%v]", i, got, want)
116 }
117 }
118 }
119
120 func TestLiteralString(t *testing.T) {
121 proto := `"string"`
122 p := newParserOn(proto)
123 l := new(Literal)
124 if err := l.parse(p); err != nil {
125 t.Fatal(err)
126 }
127 if got, want := l.IsString, true; got != want {
128 t.Errorf("got [%v] want [%v]", got, want)
129 }
130 if got, want := l.Source, "string"; got != want {
131 t.Errorf("got [%v] want [%v]", got, want)
132 }
133 }
134
135 func TestOptionComments(t *testing.T) {
136 proto := `
137 // comment
138 option Help = "me"; // inline`
139 p := newParserOn(proto)
140 pr, err := p.Parse()
141 if err != nil {
142 t.Fatal(err)
143 }
144 o := pr.Elements[0].(*Option)
145 if got, want := o.IsEmbedded, false; got != want {
146 t.Errorf("got [%v] want [%v]", got, want)
147 }
148 if got, want := o.Comment != nil, true; got != want {
149 t.Fatalf("got [%v] want [%v]", got, want)
150 }
151 if got, want := o.Comment.Lines[0], " comment"; got != want {
152 t.Fatalf("got [%v] want [%v]", got, want)
153 }
154 if got, want := o.InlineComment != nil, true; got != want {
155 t.Fatalf("got [%v] want [%v]", got, want)
156 }
157 if got, want := o.InlineComment.Lines[0], " inline"; got != want {
158 t.Fatalf("got [%v] want [%v]", got, want)
159 }
160 if got, want := o.Position.Line, 3; got != want {
161 t.Fatalf("got [%v] want [%v]", got, want)
162 }
163 if got, want := o.Comment.Position.Line, 2; got != want {
164 t.Fatalf("got [%v] want [%v]", got, want)
165 }
166 if got, want := o.InlineComment.Position.Line, 3; got != want {
167 t.Fatalf("got [%v] want [%v]", got, want)
168 }
169 }
170
171 func TestAggregateSyntax(t *testing.T) {
172 proto := `
173 // usage:
174 message Bar {
175 // alternative aggregate syntax (uses TextFormat):
176 int32 b = 2 [(foo_options) = {
177 opt1: 123,
178 opt2: "baz"
179 }];
180 }
181 `
182 p := newParserOn(proto)
183 pr, err := p.Parse()
184 if err != nil {
185 t.Fatal(err)
186 }
187 o := pr.Elements[0].(*Message)
188 f := o.Elements[0].(*NormalField)
189 if got, want := len(f.Options), 1; got != want {
190 t.Fatalf("got [%v] want [%v]", got, want)
191 }
192 ac := f.Options[0].Constant.Map
193 if got, want := len(ac), 2; got != want {
194 t.Fatalf("got [%v] want [%v]", got, want)
195 }
196 if got, want := ac["opt1"].Source, "123"; got != want {
197 t.Fatalf("got [%v] want [%v]", got, want)
198 }
199 if got, want := o.Position.Line, 3; got != want {
200 t.Fatalf("got [%v] want [%v]", got, want)
201 }
202 if got, want := o.Comment.Position.String(), "<input>:2:1"; got != want {
203 t.Fatalf("got [%v] want [%v]", got, want)
204 }
205 if got, want := f.Position.String(), "<input>:5:3"; got != want {
206 t.Fatalf("got [%v] want [%v]", got, want)
207 }
208 if got, want := f.Options[0].Constant.Position.Line, 5; got != want {
209 t.Fatalf("got [%v] want [%v]", got, want)
210 }
211
212 list := f.Options[0].AggregatedConstants
213 if got, want := list[0].Source, "123"; got != want {
214 t.Fatalf("got [%v] want [%v]", got, want)
215 }
216 if got, want := list[1].Source, "baz"; got != want {
217 t.Fatalf("got [%v] want [%v]", got, want)
218 }
219 }
220
221 func TestNonPrimitiveOptionComment(t *testing.T) {
222 proto := `
223 // comment
224 option Help = { string_field: "value" }; // inline`
225 p := newParserOn(proto)
226 pr, err := p.Parse()
227 if err != nil {
228 t.Fatal(err)
229 }
230 o := pr.Elements[0].(*Option)
231 if got, want := o.Comment != nil, true; got != want {
232 t.Fatalf("got [%v] want [%v]", got, want)
233 }
234 if got, want := o.Comment.Lines[0], " comment"; got != want {
235 t.Fatalf("got [%v] want [%v]", got, want)
236 }
237 if got, want := o.InlineComment != nil, true; got != want {
238 t.Fatalf("got [%v] want [%v]", got, want)
239 }
240 if got, want := o.InlineComment.Lines[0], " inline"; got != want {
241 t.Fatalf("got [%v] want [%v]", got, want)
242 }
243 }
244
245 func TestFieldCustomOptions(t *testing.T) {
246 proto := `foo.bar lots = 1 [foo={hello:1}, bar=2];`
247 p := newParserOn(proto)
248 f := newNormalField()
249 err := f.parse(p)
250 if err != nil {
251 t.Fatal(err)
252 }
253 if got, want := f.Type, "foo.bar"; got != want {
254 t.Errorf("got [%v] want [%v]", got, want)
255 }
256 if got, want := f.Name, "lots"; got != want {
257 t.Errorf("got [%v] want [%v]", got, want)
258 }
259 if got, want := len(f.Options), 2; got != want {
260 t.Fatalf("got [%v] want [%v]", got, want)
261 }
262 if got, want := f.Options[0].Name, "foo"; got != want {
263 t.Errorf("got [%v] want [%v]", got, want)
264 }
265 if got, want := f.Options[1].Name, "bar"; got != want {
266 t.Errorf("got [%v] want [%v]", got, want)
267 }
268 if got, want := f.Options[1].Constant.Source, "2"; got != want {
269 t.Errorf("got [%v] want [%v]", got, want)
270 }
271
272 if got, want := f.Options[0].AggregatedConstants[0].Name, "hello"; got != want {
273 t.Errorf("got [%v] want [%v]", got, want)
274 }
275 if got, want := f.Options[0].AggregatedConstants[0].PrintsColon, true; got != want {
276 t.Errorf("got [%v] want [%v]", got, want)
277 }
278 if got, want := f.Options[0].AggregatedConstants[0].Source, "1"; got != want {
279 t.Errorf("got [%v] want [%v]", got, want)
280 }
281 }
282
283 func TestIgnoreIllegalEscapeCharsInAggregatedConstants(t *testing.T) {
284 src := `syntax = "proto3";
285 message Person {
286 string name = 3 [(validate.rules).string = {
287 pattern: "^[^\d\s]+( [^\d\s]+)*$",
288 max_bytes: 256,
289 }];
290 }`
291 p := newParserOn(src)
292 d, err := p.Parse()
293 if err != nil {
294 t.Fatal(err)
295 }
296 f := d.Elements[1].(*Message).Elements[0].(*NormalField)
297 if got, want := f.Options[0].Name, "(validate.rules).string"; got != want {
298 t.Errorf("got [%v] want [%v]", got, want)
299 }
300 if got, want := len(f.Options[0].Constant.Map), 2; got != want {
301 t.Errorf("got [%v] want [%v]", got, want)
302 }
303 if got, want := f.Options[0].Constant.Map["pattern"].Source, "^[^\\d\\s]+( [^\\d\\s]+)*$"; got != want {
304 t.Errorf("got [%v] want [%v]", got, want)
305 }
306 if got, want := len(f.Options[0].Constant.OrderedMap), 2; got != want {
307 t.Errorf("got [%v] want [%v]", got, want)
308 }
309 if got, want := f.Options[0].Constant.OrderedMap[0].Name, "pattern"; got != want {
310 t.Errorf("got [%v] want [%v]", got, want)
311 }
312 if got, want := f.Options[0].Constant.OrderedMap[0].Source, "^[^\\d\\s]+( [^\\d\\s]+)*$"; got != want {
313 t.Errorf("got [%v] want [%v]", got, want)
314 }
315
316 if got, want := f.Options[0].AggregatedConstants[0].Name, "pattern"; got != want {
317 t.Errorf("got [%v] want [%v]", got, want)
318 }
319 if got, want := f.Options[0].AggregatedConstants[0].PrintsColon, true; got != want {
320 t.Errorf("got [%v] want [%v]", got, want)
321 }
322 if got, want := f.Options[0].AggregatedConstants[0].Source, "^[^\\d\\s]+( [^\\d\\s]+)*$"; got != want {
323 t.Errorf("got [%v] want [%v]", got, want)
324 }
325 }
326
327 func TestIgnoreIllegalEscapeCharsInConstant(t *testing.T) {
328 src := `syntax = "proto2";
329 message Person {
330 optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
331 }`
332 p := newParserOn(src)
333 d, err := p.Parse()
334 if err != nil {
335 t.Fatal(err)
336 }
337 f := d.Elements[1].(*Message).Elements[0].(*NormalField)
338 if got, want := f.Options[0].Constant.Source, "? \\? ?? \\?? \\??? ??/ ?\\?-"; got != want {
339 t.Errorf("got [%v] want [%v]", got, want)
340 }
341 }
342
343 func TestFieldCustomOptionExtendedIdent(t *testing.T) {
344 proto := `Type field = 1 [(validate.rules).enum.defined_only = true];`
345 p := newParserOn(proto)
346 f := newNormalField()
347 err := f.parse(p)
348 if err != nil {
349 t.Fatal(err)
350 }
351 if got, want := f.Options[0].Name, "(validate.rules).enum.defined_only"; got != want {
352 t.Errorf("got [%v] want [%v]", got, want)
353 }
354 }
355
356
357 func TestNestedAggregateConstants(t *testing.T) {
358 src := `syntax = "proto3";
359
360 package baz;
361
362 option (foo.bar) = {
363 woot: 100
364 foo {
365 hello: 200
366 hello2: 300
367 bar {
368 hello3: 400
369 }
370 }
371 };`
372 p := newParserOn(src)
373 proto, err := p.Parse()
374 if err != nil {
375 t.Error(err)
376 }
377 option := proto.Elements[2].(*Option)
378 if got, want := option.Name, "(foo.bar)"; got != want {
379 t.Errorf("got [%v] want [%v]", got, want)
380 }
381 if got, want := len(option.Constant.Map), 2; got != want {
382 t.Errorf("got [%v] want [%v]", got, want)
383 }
384 m := option.Constant.Map
385 if got, want := m["woot"].Source, "100"; got != want {
386 t.Errorf("got [%v] want [%v]", got, want)
387 }
388 if got, want := len(m["foo"].Map), 3; got != want {
389 t.Errorf("got [%v] want [%v]", got, want)
390 }
391 m = m["foo"].Map
392 if got, want := len(m["bar"].Map), 1; got != want {
393 t.Errorf("got [%v] want [%v]", got, want)
394 }
395 if got, want := m["bar"].Map["hello3"].Source, "400"; got != want {
396 t.Errorf("got [%v] want [%v]", got, want)
397 }
398 if got, want := option.Constant.OrderedMap[1].Name, "foo"; got != want {
399 t.Errorf("got [%v] want [%v]", got, want)
400 }
401 if got, want := option.Constant.OrderedMap[1].OrderedMap[2].Name, "bar"; got != want {
402 t.Errorf("got [%v] want [%v]", got, want)
403 }
404 if got, want := option.Constant.OrderedMap[1].OrderedMap[2].OrderedMap[0].Source, "400"; got != want {
405 t.Errorf("got [%v] want [%v]", got, want)
406 }
407 if got, want := len(option.AggregatedConstants), 4; got != want {
408 t.Errorf("got [%v] want [%v]", got, want)
409 }
410
411
412
413 }
414
415
416 func TestMultiLineOptionAggregateValue(t *testing.T) {
417 src := `rpc ListTransferLogs(ListTransferLogsRequest)
418 returns (ListTransferLogsResponse) {
419 option (google.api.http) = {
420 get: "/v1/{parent=projects/*/locations/*/transferConfigs/*/runs/*}/"
421 "transferLogs"
422 };
423 }`
424 p := newParserOn(src)
425 rpc := new(RPC)
426 p.next()
427 err := rpc.parse(p)
428 if err != nil {
429 t.Error(err)
430 }
431 get := rpc.Options[0].Constant.Map["get"]
432 if got, want := get.Source, "/v1/{parent=projects/*/locations/*/transferConfigs/*/runs/*}/transferLogs"; got != want {
433 t.Errorf("got [%v] want [%v]", got, want)
434 }
435 }
436
437
438 func TestOptionAggregateCanUseKeyword(t *testing.T) {
439 src := `message User {
440 string email = 3 [(validate.field) = {required: true}];
441 }`
442 p := newParserOn(src)
443 _, err := p.Parse()
444 if err != nil {
445 t.Error(err)
446 }
447 }
448
449
450 func TestOptionAggregateWithRepeatedValues(t *testing.T) {
451 src := `message Envelope {
452 int64 not_in = 15 [(validate.rules).int64 = {not_in: [40, 45]}];
453 int64 in = 16 [(validate.rules).int64 = {in: [[1],[2]]}];
454 }`
455 p := newParserOn(src)
456 def, err := p.Parse()
457 if err != nil {
458 t.Error(err)
459 }
460 field := def.Elements[0].(*Message).Elements[0].(*NormalField)
461 notIn := field.Options[0].Constant.Map["not_in"]
462 if got, want := len(notIn.Array), 2; got != want {
463 t.Errorf("got [%v] want [%v]", got, want)
464 }
465 if got, want := notIn.Array[0].Source, "40"; got != want {
466 t.Errorf("got [%v] want [%v]", got, want)
467 }
468 if got, want := notIn.Array[1].Source, "45"; got != want {
469 t.Errorf("got [%v] want [%v]", got, want)
470 }
471 }
472
473 func TestInvalidOptionAggregateWithRepeatedValues(t *testing.T) {
474 src := `message Bogus {
475 int64 a = 1 [a = {not_in: [40 syntax]}];
476 }`
477 p := newParserOn(src)
478 _, err := p.Parse()
479 if err == nil {
480 t.Error("expected syntax error")
481 }
482 }
483
484
485 func TestUseOfSemicolonsInAggregatedConstants(t *testing.T) {
486 src := `rpc Test(Void) returns (Void) {
487 option (google.api.http) = {
488 post: "/api/v1/test";
489 body: "*"; // ignored comment
490 };
491 }`
492 p := newParserOn(src)
493 rpc := new(RPC)
494 p.next()
495 err := rpc.parse(p)
496 if err != nil {
497 t.Fatal(err)
498 }
499 if got, want := len(rpc.Elements), 1; got != want {
500 t.Errorf("got [%v] want [%v]", got, want)
501 }
502 opt := rpc.Elements[0].(*Option)
503 if got, want := len(opt.Constant.Map), 2; got != want {
504 t.Fatalf("got [%v] want [%v]", got, want)
505 }
506
507 if got, want := opt.Constant.Map["body"].Source, "*"; got != want {
508 t.Errorf("got [%v] want [%v]", got, want)
509 }
510
511 body, ok := opt.Constant.OrderedMap.Get("body")
512 if !ok {
513 t.Fatal("expected body key")
514 }
515 if got, want := body.Source, "*"; got != want {
516 t.Errorf("got [%v] want [%v]", got, want)
517 }
518
519
520
521 }
522
523 func TestParseNestedSelectorInAggregatedConstant(t *testing.T) {
524 src := `rpc Test(Void) returns (Void) {
525 option (google.api.http) = {
526 get: "/api/v1/test"
527 additional_bindings.post: "/api/v1/test"
528 additional_bindings.body: "*"
529 };
530 }`
531 p := newParserOn(src)
532 rpc := new(RPC)
533 p.next()
534 err := rpc.parse(p)
535 if err != nil {
536 t.Fatal(err)
537 }
538 if got, want := rpc.Options[0].Constant.Map["get"].Source, "/api/v1/test"; got != want {
539 t.Errorf("got [%v] want [%v]", got, want)
540 }
541 if got, want := rpc.Options[0].Constant.Map["additional_bindings.post"].Source, "/api/v1/test"; got != want {
542 t.Errorf("got [%v] want [%v]", got, want)
543 }
544 if got, want := rpc.Options[0].AggregatedConstants[2].Name, "additional_bindings.body"; got != want {
545 t.Errorf("got [%v] want [%v]", got, want)
546 }
547 if got, want := rpc.Options[0].AggregatedConstants[2].Source, "*"; got != want {
548 t.Errorf("got [%v] want [%v]", got, want)
549 }
550 }
551
552 func TestParseMultilineStringConstant(t *testing.T) {
553 src := `message Test {
554 string description = 3 [
555 (common.ui_field_desc) = "Description of the account"
556 " domain (e.g. Team,"
557 "Name User Account Directory)."
558 ];
559 }`
560 p := newParserOn(src)
561 m := new(Message)
562 p.next()
563 err := m.parse(p)
564 if err != nil {
565 t.Fatal(err)
566 }
567 s := m.Elements[0].(*NormalField).Options[0].Constant.Source
568 if got, want := s, "Description of the account domain (e.g. Team,Name User Account Directory)."; got != want {
569 t.Errorf("got [%v] want [%v]", got, want)
570 }
571 }
572
573 func TestOptionWithRepeatedMessageValues(t *testing.T) {
574 src := `message Foo {
575 int64 a = 1 [b = {repeated_message_field: [{hello: 1}, {hello: 2}]}];
576 }`
577 p := newParserOn(src)
578 def, err := p.Parse()
579 if err != nil {
580 t.Errorf("expected no error but got %v", err)
581 }
582 opt := def.Elements[0].(*Message).Elements[0].(*NormalField).Options[0]
583 hello, ok := opt.AggregatedConstants[0].Array[0].OrderedMap.Get("hello")
584 if !ok {
585 t.Fail()
586 }
587 if got, want := hello.SourceRepresentation(), "1"; got != want {
588 t.Errorf("got [%v] want [%v]", got, want)
589 }
590 }
591
592 func TestOptionWithRepeatedMessageValuesWithArray(t *testing.T) {
593 src := `message Foo {
594 int64 a = 1 [ (bar.repeated_field_dep_option) =
595 { hello: 1, repeated_dep: [
596 { hello: 1, repeated_bar: [1, 2] },
597 { hello: 3, repeated_bar: [3, 4] } ] } ];
598 }`
599 p := newParserOn(src)
600 def, err := p.Parse()
601 if err != nil {
602 t.Errorf("expected no error but got %v", err)
603 }
604 opt := def.Elements[0].(*Message).Elements[0].(*NormalField).Options[0]
605 hello, ok := opt.Constant.OrderedMap.Get("hello")
606 if !ok {
607 t.Fail()
608 }
609 if got, want := hello.SourceRepresentation(), "1"; got != want {
610 t.Errorf("got [%v] want [%v]", got, want)
611 }
612 repeatedDep, ok := opt.Constant.OrderedMap.Get("repeated_dep")
613 if !ok {
614 t.Fail()
615 }
616 if got, want := len(repeatedDep.Array), 2; got != want {
617 t.Errorf("got [%v] want [%v]", got, want)
618 }
619 hello, ok = repeatedDep.Array[0].OrderedMap.Get("hello")
620 if !ok {
621 t.Fail()
622 }
623 if got, want := hello.SourceRepresentation(), "1"; got != want {
624 t.Errorf("got [%v] want [%v]", got, want)
625 }
626 onetwo, ok := repeatedDep.Array[0].OrderedMap.Get("repeated_bar")
627 if !ok {
628 t.Fail()
629 }
630 if got, want := onetwo.Array[0].Source, "1"; got != want {
631 t.Errorf("got [%v] want [%v]", got, want)
632 }
633 if got, want := onetwo.Array[1].Source, "2"; got != want {
634 t.Errorf("got [%v] want [%v]", got, want)
635 }
636 }
637
638
639 func TestFieldCustomOptionLeadingDot(t *testing.T) {
640 proto := `string app_entity_id = 4 [(.common.v1.some_custom_option) = { opt1: true opt2: false }];`
641 p := newParserOn(proto)
642 f := newNormalField()
643 err := f.parse(p)
644 if err != nil {
645 t.Fatal(err)
646 }
647 if got, want := f.Type, "string"; got != want {
648 t.Errorf("got [%v] want [%v]", got, want)
649 }
650 o := f.Options[0]
651 if got, want := o.Name, "(.common.v1.some_custom_option)"; got != want {
652 t.Fatalf("got [%v] want [%v]", got, want)
653 }
654 }
655
656
657 func TestEmptyArrayInOptionStructure(t *testing.T) {
658 src := `
659 option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
660 json_schema : {
661 title : "Frob a request"
662 description : "blah blah blah"
663 required : [ ]
664 optional:["this"]
665 }
666 };
667 `
668 p := newParserOn(src)
669 p.next()
670 o := new(Option)
671 if err := o.parse(p); err != nil {
672 t.Fatal("testcase parse failed:", err)
673 }
674 s, ok := o.Constant.OrderedMap.Get("json_schema")
675 if !ok {
676 t.Fatal("expected json_schema literal")
677 }
678
679 a, ok := s.OrderedMap.Get("required")
680 if !ok {
681 t.Fatal("expected required literal")
682 }
683 if len(a.Array) != 0 {
684 t.Fatal("expecting empty array")
685 }
686
687 a, ok = s.OrderedMap.Get("optional")
688 if !ok {
689 t.Fatal("expected required literal")
690 }
691 if len(a.Array) != 1 {
692 t.Fatal("expecting one size array")
693 }
694 if got, want := a.Array[0].Source, "this"; got != want {
695 t.Fatalf("got [%s] want [%s]", got, want)
696 }
697 }
698
699
700 func TestQuoteNotDroppedInOption(t *testing.T) {
701 src := `string name = 1 [ quote = '<="foo"' ];`
702 f := newNormalField()
703 if err := f.parse(newParserOn(src)); err != nil {
704 t.Fatal(err)
705 }
706 sr := f.Options[0].Constant.SourceRepresentation()
707 if got, want := sr, `'<="foo"'`; got != want {
708 t.Errorf("got [%s] want [%s]", got, want)
709 }
710 }
711
712 func TestWhatYouTypeIsWhatYouGetOptionValue(t *testing.T) {
713 src := `string n = 1 [ quote = 'm"\"/"' ];`
714 f := newNormalField()
715 if err := f.parse(newParserOn(src)); err != nil {
716 t.Fatal(err)
717 }
718 sr := f.Options[0].Constant.SourceRepresentation()
719 if got, want := sr, `'m"\"/"'`; got != want {
720 t.Errorf("got [%s] want [%s]", got, want)
721 }
722 }
723
724 func TestLiteralNoQuoteRuneSet(t *testing.T) {
725 l := Literal{
726 Source: "foo",
727 IsString: true,
728 }
729 if got, want := l.SourceRepresentation(), "\"foo\""; got != want {
730 t.Errorf("got [%s] want [%s]", got, want)
731 }
732 }
733
734 func TestStringValuesParsedAsNumbers(t *testing.T) {
735 src := `VAL0 = 0 [(enum_opt) = '09'];`
736 f := new(EnumField)
737 if err := f.parse(newParserOn(src)); err != nil {
738 t.Fatal(err)
739 }
740 if got, want := f.ValueOption.Constant.Source, "09"; got != want {
741 t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want)
742 }
743 }
744
745 func TestCommentInsideArray(t *testing.T) {
746 src := `option test = {
747 scope_rules : [
748 // A comment
749 // Another comment
750 {has : [
751 // comment on test
752 "test"
753 ]}
754 ]
755 };
756 `
757 opt, err := newParserOn(src).Parse()
758 if err != nil {
759 t.Fatal(err)
760 }
761 opt2 := opt.Elements[0].(*Option)
762 scp, _ := opt2.Constant.OrderedMap.Get("scope_rules")
763 elem0 := scp.Array[0]
764 t.Log("comment:", elem0.Comment.Lines)
765 has, _ := elem0.OrderedMap.Get("has")
766 if got, want := has.Array[0].Source, "test"; got != want {
767 t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want)
768 }
769 t.Log("comment:", has.Array[0].Comment.Lines)
770 }
771
View as plain text