-
Notifications
You must be signed in to change notification settings - Fork 0
/
path_test.go
114 lines (107 loc) · 3.08 KB
/
path_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package protoparts
import (
"math/rand"
"slices"
"testing"
"github.com/obeattie/protoparts/internal/testproto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protowire"
)
func TestDecodePath(t *testing.T) {
for i := 0; i < 1000; i++ {
depth := rand.Intn(100)
vp := make(Path, depth)
for i := 0; i < depth; i++ {
vp[i].Tag = protowire.Number(rand.Int31())
if rand.Float32() > 0.5 {
vp[i].Index = rand.Int()
}
if rand.Float32() > 0.5 {
key := make([]byte, rand.Intn(100))
rand.Read(key)
vp[i].Key = key
}
}
vp2 := DecodePath(vp.String())
assert.True(t, vp.Equal(vp2), `path: "%v"`, vp)
assert.Equal(t, vp.String(), vp2.String())
}
}
func TestDecodeSymbolicPath(t *testing.T) {
md := (&testproto.Person{}).ProtoReflect().Descriptor()
type tc struct {
string
Path
}
cases := []tc{
{"address", Path{{2, -1, nil}}},
{"address/city", Path{{2, -1, nil}, {2, -1, nil}}},
{"moar_addresses", Path{{3, -1, nil}}},
{"moar_addresses[2]", Path{{3, 2, nil}}},
{"moar_addresses[2]/city", Path{{3, 2, nil}, {2, -1, nil}}},
{"map_string_string[0x68656c6c6f]", Path{{10, -1, []byte("hello")}}},
{"map_string_string[2][0x68656c6c6f]", Path{{10, 2, []byte("hello")}}},
{"address.city", nil}, // invalid paths = nil
{"boopboopboop", nil},
{"map_string_string[0x68656c6c6f][2]", nil},
}
for _, c := range cases {
t.Run(c.string, func(t *testing.T) {
expected := c.Path
actual := DecodeSymbolicPath(c.string, md)
assert.Equal(t, expected, actual)
if actual != nil {
ss, err := actual.SymbolicString(md)
require.NoError(t, err)
assert.Equal(t, c.string, ss)
}
})
}
}
func TestPathHasPrefix(t *testing.T) {
type tc struct {
p string
prefix string
bool
}
cases := []tc{
{"1", "1", true},
{"1", "2", false},
{"1/2", "1/2", true},
{"1/2", "1/2/3", false},
{"1/2", "1/1", false},
{"1/2", "1", true},
{"1/2", "2", false},
{"1[1]", "1[1]", true},
{"1[1]", "1", true},
{"1[1]", "2", false},
{"1[1]", "1[2]", false},
{"1[0x0a]", "1[0x0a]", true},
{"1[0x0a]", "1[0x0b]", false},
{"1[0x0a]", "1", true},
{"", "", true},
{"1", "", true},
}
for _, c := range cases {
t.Run(c.p, func(t *testing.T) {
p, prefix := DecodePath(c.p), DecodePath(c.prefix)
actual := p.HasPrefix(prefix)
assert.Equal(t, c.bool, actual, "(%v).HasPrefix(%v) ≠ %v", c.p, c.prefix, c.bool)
assert.False(t, p.HasPrefix(nil), "(%v).HasPrefix(nil) should return false", c.p)
})
}
}
func TestPathAppend(t *testing.T) {
// Check that Append() is not susceptible to overwriting other arrays à la https://go.dev/play/p/ZgbQkw0lF5S
a := slices.Grow(DecodePath("1/2/3"), 10)
b := a.Append(DecodePath("4"))
c := a.Append(DecodePath("40"))
assert.Equal(t, DecodePath("1/2/3"), a)
assert.Equal(t, DecodePath("1/2/3/4"), b)
assert.Equal(t, DecodePath("1/2/3/40"), c)
// Nil handling
assert.Equal(t, DecodePath("1/2/3"), DecodePath("1/2/3").Append(nil))
assert.Equal(t, DecodePath("1/2/3"), Path(nil).Append(DecodePath("1/2/3")))
assert.Nil(t, Path(nil).Append(nil))
}