OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package datastore | 5 package datastore |
6 | 6 |
7 import ( | 7 import ( |
8 "encoding/json" | 8 "encoding/json" |
9 "fmt" | 9 "fmt" |
10 "testing" | 10 "testing" |
11 | 11 |
12 . "github.com/luci/luci-go/common/testing/assertions" | 12 . "github.com/luci/luci-go/common/testing/assertions" |
13 . "github.com/smartystreets/goconvey/convey" | 13 . "github.com/smartystreets/goconvey/convey" |
14 ) | 14 ) |
15 | 15 |
16 func ShouldEqualKey(actual interface{}, expected ...interface{}) string { | 16 func ShouldEqualKey(actual interface{}, expected ...interface{}) string { |
17 if len(expected) != 1 { | 17 if len(expected) != 1 { |
18 return fmt.Sprintf("Assertion requires 1 expected value, got %d"
, len(expected)) | 18 return fmt.Sprintf("Assertion requires 1 expected value, got %d"
, len(expected)) |
19 } | 19 } |
20 if actual.(*Key).Equal(expected[0].(*Key)) { | 20 if actual.(*Key).Equal(expected[0].(*Key)) { |
21 return "" | 21 return "" |
22 } | 22 } |
23 return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0]) | 23 return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0]) |
24 } | 24 } |
25 | 25 |
26 func TestKeyEncode(t *testing.T) { | 26 func TestKeyEncode(t *testing.T) { |
27 t.Parallel() | 27 t.Parallel() |
28 | 28 |
| 29 kc := KeyContext{"appid", "ns"} |
29 keys := []*Key{ | 30 keys := []*Key{ |
30 » » MakeKey("appid", "ns", "kind", 1), | 31 » » kc.MakeKey("kind", 1), |
31 » » MakeKey("appid", "ns", "nerd", "moo"), | 32 » » kc.MakeKey("nerd", "moo"), |
32 » » MakeKey("appid", "ns", "parent", 10, "renerd", "moo"), | 33 » » kc.MakeKey("parent", 10, "renerd", "moo"), |
33 } | 34 } |
34 | 35 |
35 Convey("Key Round trip", t, func() { | 36 Convey("Key Round trip", t, func() { |
36 for _, k := range keys { | 37 for _, k := range keys { |
37 k := k | 38 k := k |
38 Convey(k.String(), func() { | 39 Convey(k.String(), func() { |
39 enc := k.Encode() | 40 enc := k.Encode() |
40 dec, err := NewKeyEncoded(enc) | 41 dec, err := NewKeyEncoded(enc) |
41 So(err, ShouldBeNil) | 42 So(err, ShouldBeNil) |
42 So(dec, ShouldNotBeNil) | 43 So(dec, ShouldNotBeNil) |
(...skipping 11 matching lines...) Expand all Loading... |
54 | 55 |
55 dec := &Key{} | 56 dec := &Key{} |
56 So(dec.UnmarshalJSON(data), ShouldBeNil) | 57 So(dec.UnmarshalJSON(data), ShouldBeNil) |
57 So(dec, ShouldEqualKey, k) | 58 So(dec, ShouldEqualKey, k) |
58 }) | 59 }) |
59 } | 60 } |
60 }) | 61 }) |
61 | 62 |
62 Convey("NewKey", t, func() { | 63 Convey("NewKey", t, func() { |
63 Convey("single", func() { | 64 Convey("single", func() { |
64 » » » k := NewKey("appid", "ns", "kind", "", 1, nil) | 65 » » » k := KeyContext{"appid", "ns"}.NewKey("kind", "", 1, nil
) |
65 So(k, ShouldEqualKey, keys[0]) | 66 So(k, ShouldEqualKey, keys[0]) |
66 }) | 67 }) |
67 | 68 |
68 Convey("empty", func() { | 69 Convey("empty", func() { |
69 » » » So(NewKeyToks("appid", "ns", nil), ShouldBeNil) | 70 » » » So(KeyContext{"appid", "ns"}.NewKeyToks(nil), ShouldBeNi
l) |
70 }) | 71 }) |
71 | 72 |
72 Convey("nest", func() { | 73 Convey("nest", func() { |
73 » » » k := NewKey("appid", "ns", "renerd", "moo", 0, | 74 » » » kc := KeyContext{"appid", "ns"} |
74 » » » » NewKey("appid", "ns", "parent", "", 10, nil)) | 75 » » » k := kc.NewKey("renerd", "moo", 0, kc.NewKey("parent", "
", 10, nil)) |
75 So(k, ShouldEqualKey, keys[2]) | 76 So(k, ShouldEqualKey, keys[2]) |
76 }) | 77 }) |
77 }) | 78 }) |
78 | 79 |
79 Convey("Key bad encoding", t, func() { | 80 Convey("Key bad encoding", t, func() { |
80 Convey("extra junk before", func() { | 81 Convey("extra junk before", func() { |
81 enc := keys[2].Encode() | 82 enc := keys[2].Encode() |
82 _, err := NewKeyEncoded("/" + enc) | 83 _, err := NewKeyEncoded("/" + enc) |
83 So(err, ShouldErrLike, "illegal base64") | 84 So(err, ShouldErrLike, "illegal base64") |
84 }) | 85 }) |
85 | 86 |
86 Convey("extra junk after", func() { | 87 Convey("extra junk after", func() { |
87 enc := keys[2].Encode() | 88 enc := keys[2].Encode() |
88 _, err := NewKeyEncoded(enc[:len(enc)-1]) | 89 _, err := NewKeyEncoded(enc[:len(enc)-1]) |
89 So(err, ShouldErrLike, "EOF") | 90 So(err, ShouldErrLike, "EOF") |
90 }) | 91 }) |
91 | 92 |
92 Convey("json encoding includes quotes", func() { | 93 Convey("json encoding includes quotes", func() { |
93 data, err := keys[0].MarshalJSON() | 94 data, err := keys[0].MarshalJSON() |
94 So(err, ShouldBeNil) | 95 So(err, ShouldBeNil) |
95 | 96 |
96 dec := &Key{} | 97 dec := &Key{} |
97 err = dec.UnmarshalJSON(append(data, '!')) | 98 err = dec.UnmarshalJSON(append(data, '!')) |
98 So(err, ShouldErrLike, "bad JSON key") | 99 So(err, ShouldErrLike, "bad JSON key") |
99 }) | 100 }) |
100 }) | 101 }) |
101 } | 102 } |
102 | 103 |
103 func TestKeyValidity(t *testing.T) { | 104 func TestKeyValidity(t *testing.T) { |
104 » //t.Parallel() | 105 » t.Parallel() |
105 | 106 |
106 Convey("keys validity", t, func() { | 107 Convey("keys validity", t, func() { |
| 108 kc := KeyContext{"aid", "ns"} |
| 109 |
107 Convey("incomplete", func() { | 110 Convey("incomplete", func() { |
108 » » » So(MakeKey("aid", "ns", "kind", 1).IsIncomplete(), Shoul
dBeFalse) | 111 » » » So(kc.MakeKey("kind", 1).IsIncomplete(), ShouldBeFalse) |
109 » » » So(MakeKey("aid", "ns", "kind", 0).IsIncomplete(), Shoul
dBeTrue) | 112 » » » So(kc.MakeKey("kind", 0).IsIncomplete(), ShouldBeTrue) |
110 }) | 113 }) |
111 | 114 |
112 Convey("invalid", func() { | 115 Convey("invalid", func() { |
113 » » » So(MakeKey("aid", "ns", "hat", "face", "__kind__", 1).Va
lid(true, "aid", "ns"), ShouldBeTrue) | 116 » » » So(kc.MakeKey("hat", "face", "__kind__", 1).Valid(true,
kc), ShouldBeTrue) |
114 | 117 |
115 bads := []*Key{ | 118 bads := []*Key{ |
116 » » » » NewKeyToks("aid", "ns", []KeyTok{{"Kind", 1, "1"
}}), | 119 » » » » KeyContext{"aid", "ns"}.NewKeyToks([]KeyTok{{"Ki
nd", 1, "1"}}), |
117 » » » » MakeKey("", "ns", "hat", "face"), | 120 » » » » KeyContext{"", "ns"}.MakeKey("", "ns", "hat", "f
ace"), |
118 » » » » MakeKey("aid", "ns", "base", 1, "", "id"), | 121 » » » » kc.MakeKey("base", 1, "", "id"), |
119 » » » » MakeKey("aid", "ns", "hat", "face", "__kind__",
1), | 122 » » » » kc.MakeKey("hat", "face", "__kind__", 1), |
120 » » » » MakeKey("aid", "ns", "hat", 0, "kind", 1), | 123 » » » » kc.MakeKey("hat", 0, "kind", 1), |
121 } | 124 } |
122 for _, k := range bads { | 125 for _, k := range bads { |
123 Convey(k.String(), func() { | 126 Convey(k.String(), func() { |
124 » » » » » So(k.Valid(false, "aid", "ns"), ShouldBe
False) | 127 » » » » » So(k.Valid(false, kc), ShouldBeFalse) |
125 }) | 128 }) |
126 } | 129 } |
127 }) | 130 }) |
128 | 131 |
129 Convey("partially valid", func() { | 132 Convey("partially valid", func() { |
130 » » » So(MakeKey("aid", "ns", "kind", "").PartialValid("aid",
"ns"), ShouldBeTrue) | 133 » » » So(kc.MakeKey("kind", "").PartialValid(kc), ShouldBeTrue
) |
131 » » » So(MakeKey("aid", "ns", "kind", "", "child", "").Partial
Valid("aid", "ns"), ShouldBeFalse) | 134 » » » So(kc.MakeKey("kind", "", "child", "").PartialValid(kc),
ShouldBeFalse) |
132 }) | 135 }) |
133 }) | 136 }) |
134 } | 137 } |
135 | 138 |
136 func TestMiscKey(t *testing.T) { | 139 func TestMiscKey(t *testing.T) { |
137 t.Parallel() | 140 t.Parallel() |
138 | 141 |
139 Convey("KeyRoot", t, func() { | 142 Convey("KeyRoot", t, func() { |
140 » » k := MakeKey("appid", "ns", "parent", 10, "renerd", "moo") | 143 » » kc := KeyContext{"appid", "ns"} |
141 » » r := MakeKey("appid", "ns", "parent", 10) | 144 |
| 145 » » k := kc.MakeKey("parent", 10, "renerd", "moo") |
| 146 » » r := kc.MakeKey("parent", 10) |
142 So(k.Root(), ShouldEqualKey, r) | 147 So(k.Root(), ShouldEqualKey, r) |
143 }) | 148 }) |
144 | 149 |
145 Convey("KeysEqual", t, func() { | 150 Convey("KeysEqual", t, func() { |
146 » » k1 := MakeKey("a", "n", "knd", 1) | 151 » » kc := KeyContext{"a", "n"} |
147 » » k2 := MakeKey("a", "n", "knd", 1) | 152 |
| 153 » » k1 := kc.MakeKey("knd", 1) |
| 154 » » k2 := kc.MakeKey("knd", 1) |
148 So(k1.Equal(k2), ShouldBeTrue) | 155 So(k1.Equal(k2), ShouldBeTrue) |
149 » » k3 := MakeKey("a", "n", "knd", 2) | 156 » » k3 := kc.MakeKey("knd", 2) |
150 So(k1.Equal(k3), ShouldBeFalse) | 157 So(k1.Equal(k3), ShouldBeFalse) |
151 }) | 158 }) |
152 | 159 |
153 Convey("KeyString", t, func() { | 160 Convey("KeyString", t, func() { |
154 » » k1 := MakeKey("a", "n", "knd", 1, "other", "wat") | 161 » » kc := KeyContext{"a", "n"} |
| 162 |
| 163 » » k1 := kc.MakeKey("knd", 1, "other", "wat") |
155 So(k1.String(), ShouldEqual, "a:n:/knd,1/other,\"wat\"") | 164 So(k1.String(), ShouldEqual, "a:n:/knd,1/other,\"wat\"") |
156 }) | 165 }) |
157 | 166 |
158 Convey("HasAncestor", t, func() { | 167 Convey("HasAncestor", t, func() { |
159 » » k1 := MakeKey("a", "n", "kind", 1) | 168 » » kc := KeyContext{"a", "n"} |
160 » » k2 := MakeKey("a", "n", "kind", 1, "other", "wat") | 169 |
161 » » k3 := MakeKey("a", "n", "kind", 1, "other", "wat", "extra", "dat
a") | 170 » » k1 := kc.MakeKey("kind", 1) |
162 » » k4 := MakeKey("something", "n", "kind", 1) | 171 » » k2 := kc.MakeKey("kind", 1, "other", "wat") |
163 » » k5 := MakeKey("a", "n", "kind", 1, "other", "meep") | 172 » » k3 := kc.MakeKey("kind", 1, "other", "wat", "extra", "data") |
| 173 » » k4 := KeyContext{"something", "n"}.MakeKey("kind", 1) |
| 174 » » k5 := kc.MakeKey("kind", 1, "other", "meep") |
164 | 175 |
165 So(k1.HasAncestor(k1), ShouldBeTrue) | 176 So(k1.HasAncestor(k1), ShouldBeTrue) |
166 So(k1.HasAncestor(k2), ShouldBeFalse) | 177 So(k1.HasAncestor(k2), ShouldBeFalse) |
167 So(k2.HasAncestor(k5), ShouldBeFalse) | 178 So(k2.HasAncestor(k5), ShouldBeFalse) |
168 So(k5.HasAncestor(k2), ShouldBeFalse) | 179 So(k5.HasAncestor(k2), ShouldBeFalse) |
169 So(k2.HasAncestor(k1), ShouldBeTrue) | 180 So(k2.HasAncestor(k1), ShouldBeTrue) |
170 So(k3.HasAncestor(k2), ShouldBeTrue) | 181 So(k3.HasAncestor(k2), ShouldBeTrue) |
171 So(k3.HasAncestor(k1), ShouldBeTrue) | 182 So(k3.HasAncestor(k1), ShouldBeTrue) |
172 So(k3.HasAncestor(k4), ShouldBeFalse) | 183 So(k3.HasAncestor(k4), ShouldBeFalse) |
173 }) | 184 }) |
174 | 185 |
175 Convey("*GenericKey supports json encoding", t, func() { | 186 Convey("*GenericKey supports json encoding", t, func() { |
176 type TestStruct struct { | 187 type TestStruct struct { |
177 Key *Key | 188 Key *Key |
178 } | 189 } |
179 t := &TestStruct{ | 190 t := &TestStruct{ |
180 » » » NewKey("aid", "ns", "kind", "id", 0, | 191 » » » KeyContext{"aid", "ns"}.NewKey("kind", "id", 0, |
181 » » » » NewKey("aid", "ns", "parent", "", 1, nil), | 192 » » » » KeyContext{"aid", "ns"}.NewKey("parent", "", 1,
nil), |
182 )} | 193 )} |
183 d, err := json.Marshal(t) | 194 d, err := json.Marshal(t) |
184 So(err, ShouldBeNil) | 195 So(err, ShouldBeNil) |
185 t2 := &TestStruct{} | 196 t2 := &TestStruct{} |
186 err = json.Unmarshal(d, t2) | 197 err = json.Unmarshal(d, t2) |
187 So(err, ShouldBeNil) | 198 So(err, ShouldBeNil) |
188 So(t.Key, ShouldEqualKey, t2.Key) | 199 So(t.Key, ShouldEqualKey, t2.Key) |
189 }) | 200 }) |
190 } | 201 } |
191 | 202 |
(...skipping 27 matching lines...) Expand all Loading... |
219 Convey("KeyTok.Less() works", t, func() { | 230 Convey("KeyTok.Less() works", t, func() { |
220 So((KeyTok{"a", 0, "1"}).Less(KeyTok{"b", 0, "2"}), ShouldBeTrue
) | 231 So((KeyTok{"a", 0, "1"}).Less(KeyTok{"b", 0, "2"}), ShouldBeTrue
) |
221 So((KeyTok{"b", 0, "1"}).Less(KeyTok{"a", 0, "2"}), ShouldBeFals
e) | 232 So((KeyTok{"b", 0, "1"}).Less(KeyTok{"a", 0, "2"}), ShouldBeFals
e) |
222 So((KeyTok{"kind", 0, "1"}).Less(KeyTok{"kind", 0, "2"}), Should
BeTrue) | 233 So((KeyTok{"kind", 0, "1"}).Less(KeyTok{"kind", 0, "2"}), Should
BeTrue) |
223 So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 2, ""}), ShouldBe
True) | 234 So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 2, ""}), ShouldBe
True) |
224 So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 0, "1"}), ShouldB
eTrue) | 235 So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 0, "1"}), ShouldB
eTrue) |
225 }) | 236 }) |
226 | 237 |
227 Convey("Key comparison works", t, func() { | 238 Convey("Key comparison works", t, func() { |
228 s := []*Key{ | 239 s := []*Key{ |
229 » » » MakeKey("A", "", "kind", 1), | 240 » » » KeyContext{"A", ""}.MakeKey("kind", 1), |
230 » » » MakeKey("A", "n", "kind", 1), | 241 » » » KeyContext{"A", "n"}.MakeKey("kind", 1), |
231 » » » MakeKey("A", "n", "kind", 1, "something", "else"), | 242 » » » KeyContext{"A", "n"}.MakeKey("kind", 1, "something", "el
se"), |
232 » » » MakeKey("A", "n", "kind", "1"), | 243 » » » KeyContext{"A", "n"}.MakeKey("kind", "1"), |
233 » » » MakeKey("A", "n", "kind", "1", "something", "else"), | 244 » » » KeyContext{"A", "n"}.MakeKey("kind", "1", "something", "
else"), |
234 » » » MakeKey("A", "n", "other", 1, "something", "else"), | 245 » » » KeyContext{"A", "n"}.MakeKey("other", 1, "something", "e
lse"), |
235 » » » MakeKey("a", "", "kind", 1), | 246 » » » KeyContext{"a", ""}.MakeKey("kind", 1), |
236 » » » MakeKey("a", "n", "kind", 1), | 247 » » » KeyContext{"a", "n"}.MakeKey("kind", 1), |
237 » » » MakeKey("a", "n", "kind", 2), | 248 » » » KeyContext{"a", "n"}.MakeKey("kind", 2), |
238 » » » MakeKey("a", "p", "aleph", 1), | 249 » » » KeyContext{"a", "p"}.MakeKey("aleph", 1), |
239 » » » MakeKey("b", "n", "kind", 2), | 250 » » » KeyContext{"b", "n"}.MakeKey("kind", 2), |
240 } | 251 } |
241 | 252 |
242 for i := 1; i < len(s); i++ { | 253 for i := 1; i < len(s); i++ { |
243 So(s[i-1], shouldBeLess, s[i]) | 254 So(s[i-1], shouldBeLess, s[i]) |
244 So(s[i-1], shouldNotBeEqual, s[i]) | 255 So(s[i-1], shouldNotBeEqual, s[i]) |
245 So(s[i], shouldNotBeEqual, s[i-1]) | 256 So(s[i], shouldNotBeEqual, s[i-1]) |
246 So(s[i], shouldNotBeLess, s[i-1]) | 257 So(s[i], shouldNotBeLess, s[i-1]) |
247 } | 258 } |
248 }) | 259 }) |
249 } | 260 } |
OLD | NEW |