1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package baggage
16
17 import (
18 "fmt"
19 "math/rand"
20 "sort"
21 "strings"
22 "testing"
23
24 "github.com/stretchr/testify/assert"
25
26 "go.opentelemetry.io/otel/internal/baggage"
27 )
28
29 var rng *rand.Rand
30
31 func init() {
32
33 rng = rand.New(rand.NewSource(1))
34 }
35
36 func TestKeyRegExp(t *testing.T) {
37
38 invalidKeyRune := []rune{
39 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
40 '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F',
41 '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
42 '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F', ' ',
43 '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?',
44 '=', '{', '}', '\x7F',
45 }
46
47 for _, ch := range invalidKeyRune {
48 assert.NotRegexp(t, keyDef, fmt.Sprintf("%c", ch))
49 }
50 }
51
52 func TestValueRegExp(t *testing.T) {
53
54 invalidValueRune := []rune{
55 '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
56 '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F',
57 '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
58 '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', '\x1E', '\x1F', ' ',
59 '"', ',', ';', '\\', '\x7F',
60 }
61
62 for _, ch := range invalidValueRune {
63 assert.NotRegexp(t, `^`+valueDef+`$`, fmt.Sprintf("invalid-%c-value", ch))
64 }
65 }
66
67 func TestParseProperty(t *testing.T) {
68 p := Property{key: "key", value: "value", hasValue: true}
69
70 testcases := []struct {
71 in string
72 expected Property
73 }{
74 {
75 in: "",
76 expected: Property{},
77 },
78 {
79 in: "key",
80 expected: Property{
81 key: "key",
82 },
83 },
84 {
85 in: "key=",
86 expected: Property{
87 key: "key",
88 hasValue: true,
89 },
90 },
91 {
92 in: "key=value",
93 expected: p,
94 },
95 {
96 in: " key=value ",
97 expected: p,
98 },
99 {
100 in: "key = value",
101 expected: p,
102 },
103 {
104 in: " key = value ",
105 expected: p,
106 },
107 {
108 in: "\tkey=value",
109 expected: p,
110 },
111 }
112
113 for _, tc := range testcases {
114 actual, err := parseProperty(tc.in)
115
116 if !assert.NoError(t, err) {
117 continue
118 }
119
120 assert.Equal(t, tc.expected.Key(), actual.Key(), tc.in)
121
122 actualV, actualOk := actual.Value()
123 expectedV, expectedOk := tc.expected.Value()
124 assert.Equal(t, expectedOk, actualOk, tc.in)
125 assert.Equal(t, expectedV, actualV, tc.in)
126 }
127 }
128
129 func TestParsePropertyError(t *testing.T) {
130 _, err := parseProperty(",;,")
131 assert.ErrorIs(t, err, errInvalidProperty)
132 }
133
134 func TestNewKeyProperty(t *testing.T) {
135 p, err := NewKeyProperty(" ")
136 assert.ErrorIs(t, err, errInvalidKey)
137 assert.Equal(t, Property{}, p)
138
139 p, err = NewKeyProperty("key")
140 assert.NoError(t, err)
141 assert.Equal(t, Property{key: "key"}, p)
142 }
143
144 func TestNewKeyValueProperty(t *testing.T) {
145 p, err := NewKeyValueProperty(" ", "")
146 assert.ErrorIs(t, err, errInvalidKey)
147 assert.Equal(t, Property{}, p)
148
149 p, err = NewKeyValueProperty("key", ";")
150 assert.ErrorIs(t, err, errInvalidValue)
151 assert.Equal(t, Property{}, p)
152
153 p, err = NewKeyValueProperty("key", "value")
154 assert.NoError(t, err)
155 assert.Equal(t, Property{key: "key", value: "value", hasValue: true}, p)
156 }
157
158 func TestPropertyValidate(t *testing.T) {
159 p := Property{}
160 assert.ErrorIs(t, p.validate(), errInvalidKey)
161
162 p.key = "k"
163 assert.NoError(t, p.validate())
164
165 p.value = ";"
166 assert.EqualError(t, p.validate(), "invalid property: inconsistent value")
167
168 p.hasValue = true
169 assert.ErrorIs(t, p.validate(), errInvalidValue)
170
171 p.value = "v"
172 assert.NoError(t, p.validate())
173 }
174
175 func TestNewEmptyBaggage(t *testing.T) {
176 b, err := New()
177 assert.NoError(t, err)
178 assert.Equal(t, Baggage{}, b)
179 }
180
181 func TestNewBaggage(t *testing.T) {
182 b, err := New(Member{key: "k", hasData: true})
183 assert.NoError(t, err)
184 assert.Equal(t, Baggage{list: baggage.List{"k": {}}}, b)
185 }
186
187 func TestNewBaggageWithDuplicates(t *testing.T) {
188
189
190
191 m := make([]Member, maxMembers+1)
192 for i := range m {
193
194 m[i] = Member{
195 key: "a",
196 value: fmt.Sprintf("%d", i),
197 hasData: true,
198 }
199 }
200 b, err := New(m...)
201 assert.NoError(t, err)
202
203
204 v := fmt.Sprintf("%d", maxMembers)
205 want := Baggage{list: baggage.List{"a": {Value: v}}}
206 assert.Equal(t, want, b)
207 }
208
209 func TestNewBaggageErrorEmptyMember(t *testing.T) {
210 _, err := New(Member{})
211 assert.ErrorIs(t, err, errInvalidMember)
212 }
213
214 func key(n int) string {
215 r := []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
216
217 b := make([]rune, n)
218 for i := range b {
219 b[i] = r[rng.Intn(len(r))]
220 }
221 return string(b)
222 }
223
224 func TestNewBaggageErrorTooManyBytes(t *testing.T) {
225 m := make([]Member, (maxBytesPerBaggageString/maxBytesPerMembers)+1)
226 for i := range m {
227 m[i] = Member{key: key(maxBytesPerMembers), hasData: true}
228 }
229 _, err := New(m...)
230 assert.ErrorIs(t, err, errBaggageBytes)
231 }
232
233 func TestNewBaggageErrorTooManyMembers(t *testing.T) {
234 m := make([]Member, maxMembers+1)
235 for i := range m {
236 m[i] = Member{key: fmt.Sprintf("%d", i), hasData: true}
237 }
238 _, err := New(m...)
239 assert.ErrorIs(t, err, errMemberNumber)
240 }
241
242 func TestBaggageParse(t *testing.T) {
243 tooLarge := key(maxBytesPerBaggageString + 1)
244
245 tooLargeMember := key(maxBytesPerMembers + 1)
246
247 m := make([]string, maxMembers+1)
248 for i := range m {
249 m[i] = fmt.Sprintf("a%d=", i)
250 }
251 tooManyMembers := strings.Join(m, listDelimiter)
252
253 testcases := []struct {
254 name string
255 in string
256 want baggage.List
257 err error
258 }{
259 {
260 name: "empty value",
261 in: "",
262 want: baggage.List(nil),
263 },
264 {
265 name: "single member empty value no properties",
266 in: "foo=",
267 want: baggage.List{
268 "foo": {Value: ""},
269 },
270 },
271 {
272 name: "single member no properties",
273 in: "foo=1",
274 want: baggage.List{
275 "foo": {Value: "1"},
276 },
277 },
278 {
279 name: "single member no properties plus",
280 in: "foo=1+1",
281 want: baggage.List{
282 "foo": {Value: "1+1"},
283 },
284 },
285 {
286 name: "single member no properties plus encoded",
287 in: "foo=1%2B1",
288 want: baggage.List{
289 "foo": {Value: "1+1"},
290 },
291 },
292 {
293 name: "single member no properties slash",
294 in: "foo=1/1",
295 want: baggage.List{
296 "foo": {Value: "1/1"},
297 },
298 },
299 {
300 name: "single member no properties slash encoded",
301 in: "foo=1%2F1",
302 want: baggage.List{
303 "foo": {Value: "1/1"},
304 },
305 },
306 {
307 name: "single member no properties equals",
308 in: "foo=1=1",
309 want: baggage.List{
310 "foo": {Value: "1=1"},
311 },
312 },
313 {
314 name: "single member no properties equals encoded",
315 in: "foo=1%3D1",
316 want: baggage.List{
317 "foo": {Value: "1=1"},
318 },
319 },
320 {
321 name: "single member with spaces",
322 in: " foo \t= 1\t\t ",
323 want: baggage.List{
324 "foo": {Value: "1"},
325 },
326 },
327 {
328 name: "single member empty value with properties",
329 in: "foo=;state=on;red",
330 want: baggage.List{
331 "foo": {
332 Value: "",
333 Properties: []baggage.Property{
334 {Key: "state", Value: "on", HasValue: true},
335 {Key: "red"},
336 },
337 },
338 },
339 },
340 {
341 name: "single member with properties",
342 in: "foo=1;state=on;red",
343 want: baggage.List{
344 "foo": {
345 Value: "1",
346 Properties: []baggage.Property{
347 {Key: "state", Value: "on", HasValue: true},
348 {Key: "red"},
349 },
350 },
351 },
352 },
353 {
354 name: "single member with value containing equal signs",
355 in: "foo=0=0=0",
356 want: baggage.List{
357 "foo": {Value: "0=0=0"},
358 },
359 },
360 {
361 name: "two members with properties",
362 in: "foo=1;state=on;red,bar=2;yellow",
363 want: baggage.List{
364 "foo": {
365 Value: "1",
366 Properties: []baggage.Property{
367 {Key: "state", Value: "on", HasValue: true},
368 {Key: "red"},
369 },
370 },
371 "bar": {
372 Value: "2",
373 Properties: []baggage.Property{{Key: "yellow"}},
374 },
375 },
376 },
377 {
378
379 name: "duplicate key",
380 in: "foo=1;state=on;red,foo=2",
381 want: baggage.List{
382 "foo": {Value: "2"},
383 },
384 },
385 {
386 name: "url encoded value",
387 in: "key1=val%252",
388 want: baggage.List{
389 "key1": {Value: "val%2"},
390 },
391 },
392 {
393 name: "invalid member: empty",
394 in: "foo=,,bar=",
395 err: errInvalidMember,
396 },
397 {
398 name: "invalid member: no key",
399 in: "=foo",
400 err: errInvalidKey,
401 },
402 {
403 name: "invalid member: no value",
404 in: "foo",
405 err: errInvalidMember,
406 },
407 {
408 name: "invalid member: invalid key",
409 in: "\\=value",
410 err: errInvalidKey,
411 },
412 {
413 name: "invalid member: invalid value",
414 in: "foo=\\",
415 err: errInvalidValue,
416 },
417 {
418 name: "invalid property: invalid key",
419 in: "foo=1;=v",
420 err: errInvalidProperty,
421 },
422 {
423 name: "invalid property: invalid value",
424 in: "foo=1;key=\\",
425 err: errInvalidProperty,
426 },
427 {
428 name: "invalid baggage string: too large",
429 in: tooLarge,
430 err: errBaggageBytes,
431 },
432 {
433 name: "invalid baggage string: member too large",
434 in: tooLargeMember,
435 err: errMemberBytes,
436 },
437 {
438 name: "invalid baggage string: too many members",
439 in: tooManyMembers,
440 err: errMemberNumber,
441 },
442 }
443
444 for _, tc := range testcases {
445 t.Run(tc.name, func(t *testing.T) {
446 actual, err := Parse(tc.in)
447 assert.ErrorIs(t, err, tc.err)
448 assert.Equal(t, Baggage{list: tc.want}, actual)
449 })
450 }
451 }
452
453 func TestBaggageString(t *testing.T) {
454 testcases := []struct {
455 name string
456 out string
457 baggage baggage.List
458 }{
459 {
460 name: "empty value",
461 out: "",
462 baggage: baggage.List(nil),
463 },
464 {
465 name: "single member empty value no properties",
466 out: "foo=",
467 baggage: baggage.List{
468 "foo": {Value: ""},
469 },
470 },
471 {
472 name: "single member no properties",
473 out: "foo=1",
474 baggage: baggage.List{
475 "foo": {Value: "1"},
476 },
477 },
478 {
479 name: "URL encoded value",
480 out: "foo=1%3D1",
481 baggage: baggage.List{
482 "foo": {Value: "1=1"},
483 },
484 },
485 {
486 name: "plus",
487 out: "foo=1%2B1",
488 baggage: baggage.List{
489 "foo": {Value: "1+1"},
490 },
491 },
492 {
493 name: "single member empty value with properties",
494 out: "foo=;red;state=on",
495 baggage: baggage.List{
496 "foo": {
497 Value: "",
498 Properties: []baggage.Property{
499 {Key: "state", Value: "on", HasValue: true},
500 {Key: "red"},
501 },
502 },
503 },
504 },
505 {
506 name: "single member with properties",
507
508
509 out: "foo=1;red;state=on;z=z=z",
510 baggage: baggage.List{
511 "foo": {
512 Value: "1",
513 Properties: []baggage.Property{
514 {Key: "state", Value: "on", HasValue: true},
515 {Key: "red"},
516 {Key: "z", Value: "z=z", HasValue: true},
517 },
518 },
519 },
520 },
521 {
522 name: "two members with properties",
523 out: "bar=2;yellow,foo=1;red;state=on",
524 baggage: baggage.List{
525 "foo": {
526 Value: "1",
527 Properties: []baggage.Property{
528 {Key: "state", Value: "on", HasValue: true},
529 {Key: "red"},
530 },
531 },
532 "bar": {
533 Value: "2",
534 Properties: []baggage.Property{{Key: "yellow"}},
535 },
536 },
537 },
538 }
539
540 orderer := func(s string) string {
541 members := strings.Split(s, listDelimiter)
542 for i, m := range members {
543 parts := strings.Split(m, propertyDelimiter)
544 if len(parts) > 1 {
545 sort.Strings(parts[1:])
546 members[i] = strings.Join(parts, propertyDelimiter)
547 }
548 }
549 sort.Strings(members)
550 return strings.Join(members, listDelimiter)
551 }
552
553 for _, tc := range testcases {
554 b := Baggage{tc.baggage}
555 assert.Equal(t, tc.out, orderer(b.String()))
556 }
557 }
558
559 func TestBaggageLen(t *testing.T) {
560 b := Baggage{}
561 assert.Equal(t, 0, b.Len())
562
563 b.list = make(baggage.List, 1)
564 assert.Equal(t, 0, b.Len())
565
566 b.list["k"] = baggage.Item{}
567 assert.Equal(t, 1, b.Len())
568 }
569
570 func TestBaggageDeleteMember(t *testing.T) {
571 key := "k"
572
573 b0 := Baggage{}
574 b1 := b0.DeleteMember(key)
575 assert.NotContains(t, b1.list, key)
576
577 b0 = Baggage{list: baggage.List{
578 key: {},
579 "other": {},
580 }}
581 b1 = b0.DeleteMember(key)
582 assert.Contains(t, b0.list, key)
583 assert.NotContains(t, b1.list, key)
584 }
585
586 func TestBaggageSetMemberEmpty(t *testing.T) {
587 _, err := Baggage{}.SetMember(Member{})
588 assert.ErrorIs(t, err, errInvalidMember)
589 }
590
591 func TestBaggageSetMember(t *testing.T) {
592 b0 := Baggage{}
593
594 key := "k"
595 m := Member{key: key, hasData: true}
596 b1, err := b0.SetMember(m)
597 assert.NoError(t, err)
598 assert.NotContains(t, b0.list, key)
599 assert.Equal(t, baggage.Item{}, b1.list[key])
600 assert.Equal(t, 0, len(b0.list))
601 assert.Equal(t, 1, len(b1.list))
602
603 m.value = "v"
604 b2, err := b1.SetMember(m)
605 assert.NoError(t, err)
606 assert.Equal(t, baggage.Item{}, b1.list[key])
607 assert.Equal(t, baggage.Item{Value: "v"}, b2.list[key])
608 assert.Equal(t, 1, len(b1.list))
609 assert.Equal(t, 1, len(b2.list))
610
611 p := properties{{key: "p"}}
612 m.properties = p
613 b3, err := b2.SetMember(m)
614 assert.NoError(t, err)
615 assert.Equal(t, baggage.Item{Value: "v"}, b2.list[key])
616 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b3.list[key])
617 assert.Equal(t, 1, len(b2.list))
618 assert.Equal(t, 1, len(b3.list))
619
620
621
622 p[0] = Property{key: "different"}
623 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b3.list[key])
624
625 p[0] = Property{key: "p"}
626
627 m = Member{key: "another", hasData: true}
628 b4, err := b3.SetMember(m)
629 assert.NoError(t, err)
630 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b3.list[key])
631 assert.NotContains(t, b3.list, m.key)
632 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b4.list[key])
633 assert.Equal(t, baggage.Item{}, b4.list[m.key])
634 assert.Equal(t, 1, len(b3.list))
635 assert.Equal(t, 2, len(b4.list))
636 }
637
638 func TestBaggageSetFalseMember(t *testing.T) {
639 b0 := Baggage{}
640
641 key := "k"
642 m := Member{key: key, hasData: false}
643 b1, err := b0.SetMember(m)
644 assert.Error(t, err)
645 assert.NotContains(t, b0.list, key)
646 assert.Equal(t, baggage.Item{}, b1.list[key])
647 assert.Equal(t, 0, len(b0.list))
648 assert.Equal(t, 0, len(b1.list))
649
650 m.value = "v"
651 b2, err := b1.SetMember(m)
652 assert.Error(t, err)
653 assert.Equal(t, baggage.Item{}, b1.list[key])
654 assert.Equal(t, baggage.Item{Value: ""}, b2.list[key])
655 assert.Equal(t, 0, len(b1.list))
656 assert.Equal(t, 0, len(b2.list))
657 }
658
659 func TestBaggageSetFalseMembers(t *testing.T) {
660 b0 := Baggage{}
661
662 key := "k"
663 m := Member{key: key, hasData: true}
664 b1, err := b0.SetMember(m)
665 assert.NoError(t, err)
666 assert.NotContains(t, b0.list, key)
667 assert.Equal(t, baggage.Item{}, b1.list[key])
668 assert.Equal(t, 0, len(b0.list))
669 assert.Equal(t, 1, len(b1.list))
670
671 m.value = "v"
672 b2, err := b1.SetMember(m)
673 assert.NoError(t, err)
674 assert.Equal(t, baggage.Item{}, b1.list[key])
675 assert.Equal(t, baggage.Item{Value: "v"}, b2.list[key])
676 assert.Equal(t, 1, len(b1.list))
677 assert.Equal(t, 1, len(b2.list))
678
679 p := properties{{key: "p"}}
680 m.properties = p
681 b3, err := b2.SetMember(m)
682 assert.NoError(t, err)
683 assert.Equal(t, baggage.Item{Value: "v"}, b2.list[key])
684 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b3.list[key])
685 assert.Equal(t, 1, len(b2.list))
686 assert.Equal(t, 1, len(b3.list))
687
688
689
690 p[0] = Property{key: "different"}
691 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b3.list[key])
692
693 p[0] = Property{key: "p"}
694
695 m = Member{key: "another"}
696 b4, err := b3.SetMember(m)
697 assert.Error(t, err)
698 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b3.list[key])
699 assert.NotContains(t, b3.list, m.key)
700 assert.Equal(t, baggage.Item{Value: "v", Properties: []baggage.Property{{Key: "p"}}}, b4.list[key])
701 assert.Equal(t, baggage.Item{}, b4.list[m.key])
702 assert.Equal(t, 1, len(b3.list))
703 assert.Equal(t, 1, len(b4.list))
704 }
705
706 func TestNilBaggageMembers(t *testing.T) {
707 assert.Nil(t, Baggage{}.Members())
708 }
709
710 func TestBaggageMembers(t *testing.T) {
711 members := []Member{
712 {
713 key: "foo",
714 value: "1",
715 properties: properties{
716 {key: "state", value: "on", hasValue: true},
717 {key: "red"},
718 },
719 hasData: true,
720 },
721 {
722 key: "bar",
723 value: "2",
724 properties: properties{
725 {key: "yellow"},
726 },
727 hasData: true,
728 },
729 }
730
731 bag := Baggage{list: baggage.List{
732 "foo": {
733 Value: "1",
734 Properties: []baggage.Property{
735 {Key: "state", Value: "on", HasValue: true},
736 {Key: "red"},
737 },
738 },
739 "bar": {
740 Value: "2",
741 Properties: []baggage.Property{{Key: "yellow"}},
742 },
743 }}
744
745 assert.ElementsMatch(t, members, bag.Members())
746 }
747
748 func TestBaggageMember(t *testing.T) {
749 bag := Baggage{list: baggage.List{"foo": {Value: "1"}}}
750 assert.Equal(t, Member{key: "foo", value: "1", hasData: true}, bag.Member("foo"))
751 assert.Equal(t, Member{}, bag.Member("bar"))
752 }
753
754 func TestMemberKey(t *testing.T) {
755 m := Member{}
756 assert.Equal(t, "", m.Key(), "even invalid values should be returned")
757
758 key := "k"
759 m.key = key
760 assert.Equal(t, key, m.Key())
761 }
762
763 func TestMemberValue(t *testing.T) {
764 m := Member{key: "k", value: "\\"}
765 assert.Equal(t, "\\", m.Value(), "even invalid values should be returned")
766
767 value := "v"
768 m.value = value
769 assert.Equal(t, value, m.Value())
770 }
771
772 func TestMemberProperties(t *testing.T) {
773 m := Member{key: "k", value: "v"}
774 assert.Nil(t, m.Properties())
775
776 p := []Property{{key: "foo"}}
777 m.properties = properties(p)
778 got := m.Properties()
779 assert.Equal(t, p, got)
780
781
782 got[0] = Property{key: "bar"}
783 assert.NotEqual(t, m.properties, got)
784 }
785
786 func TestMemberValidation(t *testing.T) {
787 m := Member{hasData: false}
788 assert.ErrorIs(t, m.validate(), errInvalidMember)
789
790 m.hasData = true
791 assert.ErrorIs(t, m.validate(), errInvalidKey)
792
793 m.key, m.value = "k", "\\"
794 assert.ErrorIs(t, m.validate(), errInvalidValue)
795
796 m.value = "v"
797 assert.NoError(t, m.validate())
798 }
799
800 func TestNewMember(t *testing.T) {
801 m, err := NewMember("", "")
802 assert.ErrorIs(t, err, errInvalidKey)
803 assert.Equal(t, Member{hasData: false}, m)
804
805 key, val := "k", "v"
806 p := Property{key: "foo"}
807 m, err = NewMember(key, val, p)
808 assert.NoError(t, err)
809 expected := Member{
810 key: key,
811 value: val,
812 properties: properties{{key: "foo"}},
813 hasData: true,
814 }
815 assert.Equal(t, expected, m)
816
817
818 val = "%zzzzz"
819 _, err = NewMember(key, val, p)
820 assert.ErrorIs(t, err, errInvalidValue)
821
822
823 val = "%3B"
824 m, err = NewMember(key, val, p)
825 expected = Member{
826 key: key,
827 value: ";",
828 properties: properties{{key: "foo"}},
829 hasData: true,
830 }
831 assert.NoError(t, err)
832 assert.Equal(t, expected, m)
833
834
835 p.key = "bar"
836 assert.Equal(t, expected, m)
837 }
838
839 func TestPropertiesValidate(t *testing.T) {
840 p := properties{{}}
841 assert.ErrorIs(t, p.validate(), errInvalidKey)
842
843 p[0].key = "foo"
844 assert.NoError(t, p.validate())
845
846 p = append(p, Property{key: "bar"})
847 assert.NoError(t, p.validate())
848 }
849
850 func TestMemberString(t *testing.T) {
851
852 member, _ := NewMember("key", "value")
853 memberStr := member.String()
854 assert.Equal(t, memberStr, "key=value")
855
856 member, _ = NewMember("key", "%3B")
857 memberStr = member.String()
858 assert.Equal(t, memberStr, "key=%3B")
859 }
860
861 var benchBaggage Baggage
862
863 func BenchmarkNew(b *testing.B) {
864 mem1, _ := NewMember("key1", "val1")
865 mem2, _ := NewMember("key2", "val2")
866 mem3, _ := NewMember("key3", "val3")
867 mem4, _ := NewMember("key4", "val4")
868
869 b.ReportAllocs()
870 b.ResetTimer()
871
872 for i := 0; i < b.N; i++ {
873 benchBaggage, _ = New(mem1, mem2, mem3, mem4)
874 }
875 }
876
877 var benchMember Member
878
879 func BenchmarkNewMember(b *testing.B) {
880 b.ReportAllocs()
881
882 for i := 0; i < b.N; i++ {
883 benchMember, _ = NewMember("key", "value")
884 }
885 }
886
887 func BenchmarkParse(b *testing.B) {
888 b.ReportAllocs()
889
890 for i := 0; i < b.N; i++ {
891 benchBaggage, _ = Parse(`userId=alice,serverNode = DF28 , isProduction = false,hasProp=stuff;propKey;propWValue=value`)
892 }
893 }
894
View as plain text