OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package datastore | 5 package dskey |
6 | 6 |
7 import ( | 7 import ( |
8 "encoding/json" | 8 "encoding/json" |
9 "fmt" | 9 "fmt" |
10 "testing" | 10 "testing" |
11 | 11 |
| 12 ds "github.com/luci/gae/service/datastore" |
| 13 . "github.com/luci/luci-go/common/testing/assertions" |
12 . "github.com/smartystreets/goconvey/convey" | 14 . "github.com/smartystreets/goconvey/convey" |
13 ) | 15 ) |
14 | 16 |
15 func mkKey(aid, ns string, elems ...interface{}) Key { | 17 func mkKey(aid, ns string, elems ...interface{}) ds.Key { |
16 if len(elems)%2 != 0 { | 18 if len(elems)%2 != 0 { |
17 panic("odd number of tokens") | 19 panic("odd number of tokens") |
18 } | 20 } |
19 » toks := make([]KeyTok, len(elems)/2) | 21 » toks := make([]ds.KeyTok, len(elems)/2) |
20 for i := 0; i < len(elems); i += 2 { | 22 for i := 0; i < len(elems); i += 2 { |
21 toks[i/2].Kind = elems[i].(string) | 23 toks[i/2].Kind = elems[i].(string) |
22 switch x := elems[i+1].(type) { | 24 switch x := elems[i+1].(type) { |
23 case string: | 25 case string: |
24 toks[i/2].StringID = x | 26 toks[i/2].StringID = x |
25 case int: | 27 case int: |
26 toks[i/2].IntID = int64(x) | 28 toks[i/2].IntID = int64(x) |
27 default: | 29 default: |
28 panic("bad token id") | 30 panic("bad token id") |
29 } | 31 } |
30 } | 32 } |
31 » return NewKeyToks(aid, ns, toks) | 33 » return NewToks(aid, ns, toks) |
32 } | 34 } |
33 | 35 |
34 func ShouldEqualKey(actual interface{}, expected ...interface{}) string { | 36 func ShouldEqualKey(actual interface{}, expected ...interface{}) string { |
35 if len(expected) != 1 { | 37 if len(expected) != 1 { |
36 return fmt.Sprintf("Assertion requires 1 expected value, got %d"
, len(expected)) | 38 return fmt.Sprintf("Assertion requires 1 expected value, got %d"
, len(expected)) |
37 } | 39 } |
38 » if KeysEqual(actual.(Key), expected[0].(Key)) { | 40 » if Equal(actual.(ds.Key), expected[0].(ds.Key)) { |
39 return "" | 41 return "" |
40 } | 42 } |
41 return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0]) | 43 return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0]) |
42 } | 44 } |
43 | 45 |
44 func TestKeyEncode(t *testing.T) { | 46 func TestKeyEncode(t *testing.T) { |
45 t.Parallel() | 47 t.Parallel() |
46 | 48 |
47 » keys := []Key{ | 49 » keys := []ds.Key{ |
48 mkKey("appid", "ns", "kind", 1), | 50 mkKey("appid", "ns", "kind", 1), |
49 mkKey("appid", "ns", "nerd", "moo"), | 51 mkKey("appid", "ns", "nerd", "moo"), |
50 mkKey("appid", "ns", "parent", 10, "renerd", "moo"), | 52 mkKey("appid", "ns", "parent", 10, "renerd", "moo"), |
51 } | 53 } |
52 | 54 |
53 Convey("Key Round trip", t, func() { | 55 Convey("Key Round trip", t, func() { |
54 for _, k := range keys { | 56 for _, k := range keys { |
55 k := k | 57 k := k |
56 Convey(k.String(), func() { | 58 Convey(k.String(), func() { |
57 » » » » enc := KeyEncode(k) | 59 » » » » enc := Encode(k) |
58 » » » » aid, ns, toks, err := KeyToksDecode(enc) | 60 » » » » aid, ns, toks, err := ToksDecode(enc) |
59 So(err, ShouldBeNil) | 61 So(err, ShouldBeNil) |
60 » » » » dec := NewKeyToks(aid, ns, toks) | 62 » » » » dec := NewToks(aid, ns, toks) |
61 So(dec, ShouldNotBeNil) | 63 So(dec, ShouldNotBeNil) |
62 So(dec, ShouldEqualKey, k) | 64 So(dec, ShouldEqualKey, k) |
63 | 65 |
64 » » » » dec2, err := NewKeyFromEncoded(enc) | 66 » » » » dec2, err := NewFromEncoded(enc) |
65 So(err, ShouldBeNil) | 67 So(err, ShouldBeNil) |
66 So(dec2, ShouldEqualKey, dec) | 68 So(dec2, ShouldEqualKey, dec) |
67 So(dec2, ShouldEqualKey, k) | 69 So(dec2, ShouldEqualKey, k) |
68 }) | 70 }) |
69 | 71 |
70 Convey(k.String()+" (json)", func() { | 72 Convey(k.String()+" (json)", func() { |
71 » » » » data, err := KeyMarshalJSON(k) | 73 » » » » data, err := MarshalJSON(k) |
72 So(err, ShouldBeNil) | 74 So(err, ShouldBeNil) |
73 | 75 |
74 » » » » aid, ns, toks, err := KeyUnmarshalJSON(data) | 76 » » » » aid, ns, toks, err := UnmarshalJSON(data) |
75 So(err, ShouldBeNil) | 77 So(err, ShouldBeNil) |
76 » » » » So(NewKeyToks(aid, ns, toks), ShouldEqualKey, k) | 78 » » » » So(NewToks(aid, ns, toks), ShouldEqualKey, k) |
77 }) | 79 }) |
78 } | 80 } |
79 }) | 81 }) |
80 | 82 |
81 Convey("NewKey", t, func() { | 83 Convey("NewKey", t, func() { |
82 Convey("single", func() { | 84 Convey("single", func() { |
83 » » » k := NewKey("appid", "ns", "kind", "", 1, nil) | 85 » » » k := New("appid", "ns", "kind", "", 1, nil) |
84 So(k, ShouldEqualKey, keys[0]) | 86 So(k, ShouldEqualKey, keys[0]) |
85 }) | 87 }) |
86 | 88 |
87 Convey("nest", func() { | 89 Convey("nest", func() { |
88 » » » k := NewKey("appid", "ns", "renerd", "moo", 0, | 90 » » » k := New("appid", "ns", "renerd", "moo", 0, |
89 » » » » NewKey("appid", "ns", "parent", "", 10, nil)) | 91 » » » » New("appid", "ns", "parent", "", 10, nil)) |
90 So(k, ShouldEqualKey, keys[2]) | 92 So(k, ShouldEqualKey, keys[2]) |
91 }) | 93 }) |
92 }) | 94 }) |
93 | 95 |
94 Convey("Key bad encoding", t, func() { | 96 Convey("Key bad encoding", t, func() { |
95 Convey("extra junk before", func() { | 97 Convey("extra junk before", func() { |
96 » » » enc := KeyEncode(keys[2]) | 98 » » » enc := Encode(keys[2]) |
97 » » » _, _, _, err := KeyToksDecode("/" + enc) | 99 » » » _, _, _, err := ToksDecode("/" + enc) |
98 So(err, ShouldErrLike, "illegal base64") | 100 So(err, ShouldErrLike, "illegal base64") |
99 }) | 101 }) |
100 | 102 |
101 Convey("extra junk after", func() { | 103 Convey("extra junk after", func() { |
102 » » » enc := KeyEncode(keys[2]) | 104 » » » enc := Encode(keys[2]) |
103 » » » _, _, _, err := KeyToksDecode(enc[:len(enc)-1]) | 105 » » » _, _, _, err := ToksDecode(enc[:len(enc)-1]) |
104 So(err, ShouldErrLike, "EOF") | 106 So(err, ShouldErrLike, "EOF") |
105 }) | 107 }) |
106 | 108 |
107 Convey("json encoding includes quotes", func() { | 109 Convey("json encoding includes quotes", func() { |
108 » » » data, err := KeyMarshalJSON(keys[0]) | 110 » » » data, err := MarshalJSON(keys[0]) |
109 So(err, ShouldBeNil) | 111 So(err, ShouldBeNil) |
110 | 112 |
111 » » » _, _, _, err = KeyUnmarshalJSON(append(data, '!')) | 113 » » » _, _, _, err = UnmarshalJSON(append(data, '!')) |
112 So(err, ShouldErrLike, "bad JSON key") | 114 So(err, ShouldErrLike, "bad JSON key") |
113 }) | 115 }) |
114 }) | 116 }) |
115 } | 117 } |
116 | 118 |
117 type dumbKey1 struct{ Key } | 119 type dumbKey1 struct{ ds.Key } |
118 | 120 |
119 func (dk dumbKey1) Namespace() string { return "ns" } | 121 func (dk dumbKey1) Namespace() string { return "ns" } |
120 func (dk dumbKey1) Parent() Key { return dk.Key } | 122 func (dk dumbKey1) Parent() ds.Key { return dk.Key } |
121 func (dk dumbKey1) String() string { return "dumbKey1" } | 123 func (dk dumbKey1) String() string { return "dumbKey1" } |
122 | 124 |
123 type dumbKey2 struct{ Key } | 125 type dumbKey2 struct{ ds.Key } |
124 | 126 |
125 /// This is the dumb part... can't have both IDs set. | 127 /// This is the dumb part... can't have both IDs set. |
126 func (dk dumbKey2) IntID() int64 { return 1 } | 128 func (dk dumbKey2) IntID() int64 { return 1 } |
127 func (dk dumbKey2) StringID() string { return "wat" } | 129 func (dk dumbKey2) StringID() string { return "wat" } |
128 | 130 |
129 func (dk dumbKey2) Kind() string { return "kind" } | 131 func (dk dumbKey2) Kind() string { return "kind" } |
130 func (dk dumbKey2) Parent() Key { return nil } | 132 func (dk dumbKey2) Parent() ds.Key { return nil } |
131 func (dk dumbKey2) Namespace() string { return "ns" } | 133 func (dk dumbKey2) Namespace() string { return "ns" } |
132 func (dk dumbKey2) AppID() string { return "aid" } | 134 func (dk dumbKey2) AppID() string { return "aid" } |
133 func (dk dumbKey2) String() string { return "dumbKey2" } | 135 func (dk dumbKey2) String() string { return "dumbKey2" } |
| 136 func (dk dumbKey2) Valid(allowSpecial bool, aid, ns string) bool { |
| 137 return Valid(dk, allowSpecial, aid, ns) |
| 138 } |
134 | 139 |
135 func TestBadKeyEncode(t *testing.T) { | 140 func TestKeyValidity(t *testing.T) { |
136 » t.Parallel() | 141 » //t.Parallel() |
137 | 142 |
138 » Convey("bad keys", t, func() { | 143 » Convey("keys validity", t, func() { |
139 Convey("incomplete", func() { | 144 Convey("incomplete", func() { |
140 » » » So(KeyIncomplete(mkKey("aid", "ns", "kind", 1)), ShouldB
eFalse) | 145 » » » So(Incomplete(mkKey("aid", "ns", "kind", 1)), ShouldBeFa
lse) |
141 » » » So(KeyIncomplete(mkKey("aid", "ns", "kind", 0)), ShouldB
eTrue) | 146 » » » So(Incomplete(mkKey("aid", "ns", "kind", 0)), ShouldBeTr
ue) |
142 }) | 147 }) |
143 | 148 |
144 Convey("invalid", func() { | 149 Convey("invalid", func() { |
145 » » » So(KeyValid(mkKey("aid", "ns", "hat", "face", "__kind__"
, 1), true, "aid", "ns"), ShouldBeTrue) | 150 » » » So(mkKey("aid", "ns", "hat", "face", "__kind__", 1).Vali
d(true, "aid", "ns"), ShouldBeTrue) |
146 | 151 |
147 » » » bads := []Key{ | 152 » » » bads := []ds.Key{ |
148 nil, | 153 nil, |
149 mkKey("", "ns", "hat", "face"), | 154 mkKey("", "ns", "hat", "face"), |
150 mkKey("aid", "ns", "base", 1, "", "id"), | 155 mkKey("aid", "ns", "base", 1, "", "id"), |
151 mkKey("aid", "ns", "hat", "face", "__kind__", 1)
, | 156 mkKey("aid", "ns", "hat", "face", "__kind__", 1)
, |
152 mkKey("aid", "ns", "hat", 0, "kind", 1), | 157 mkKey("aid", "ns", "hat", 0, "kind", 1), |
153 dumbKey1{mkKey("aid", "badNS", "hat", 1)}, | 158 dumbKey1{mkKey("aid", "badNS", "hat", 1)}, |
154 dumbKey2{}, | 159 dumbKey2{}, |
155 } | 160 } |
156 for _, k := range bads { | 161 for _, k := range bads { |
157 s := "<nil>" | 162 s := "<nil>" |
158 if k != nil { | 163 if k != nil { |
159 s = k.String() | 164 s = k.String() |
160 } | 165 } |
161 Convey(s, func() { | 166 Convey(s, func() { |
162 » » » » » So(KeyValid(k, false, "aid", "ns"), Shou
ldBeFalse) | 167 » » » » » if k != nil { |
| 168 » » » » » » So(k.Valid(false, "aid", "ns"),
ShouldBeFalse) |
| 169 » » » » » } else { |
| 170 » » » » » » So(Valid(k, false, "aid", "ns"),
ShouldBeFalse) |
| 171 » » » » » } |
163 }) | 172 }) |
164 } | 173 } |
165 }) | 174 }) |
| 175 |
| 176 Convey("partially valid", func() { |
| 177 So(mkKey("aid", "ns", "kind", "").PartialValid("aid", "n
s"), ShouldBeTrue) |
| 178 So(mkKey("aid", "ns", "kind", "", "child", "").PartialVa
lid("aid", "ns"), ShouldBeFalse) |
| 179 }) |
166 }) | 180 }) |
167 } | 181 } |
168 | 182 |
169 type keyWrap struct{ Key } | 183 type keyWrap struct{ ds.Key } |
170 | 184 |
171 func (k keyWrap) Parent() Key { | 185 func (k keyWrap) Parent() ds.Key { |
172 if k.Key.Parent() != nil { | 186 if k.Key.Parent() != nil { |
173 return keyWrap{k.Key.Parent()} | 187 return keyWrap{k.Key.Parent()} |
174 } | 188 } |
175 return nil | 189 return nil |
176 } | 190 } |
177 | 191 |
178 func TestMiscKey(t *testing.T) { | 192 func TestMiscKey(t *testing.T) { |
179 t.Parallel() | 193 t.Parallel() |
180 | 194 |
181 Convey("KeyRoot", t, func() { | 195 Convey("KeyRoot", t, func() { |
182 k := mkKey("appid", "ns", "parent", 10, "renerd", "moo") | 196 k := mkKey("appid", "ns", "parent", 10, "renerd", "moo") |
183 r := mkKey("appid", "ns", "parent", 10) | 197 r := mkKey("appid", "ns", "parent", 10) |
184 » » So(KeyRoot(k), ShouldEqualKey, r) | 198 » » So(Root(k), ShouldEqualKey, r) |
185 » » So(KeyRoot(nil), ShouldBeNil) | 199 » » So(Root(nil), ShouldBeNil) |
186 }) | 200 }) |
187 | 201 |
188 Convey("KeySplit", t, func() { | 202 Convey("KeySplit", t, func() { |
189 // keyWrap forces KeySplit to not take the GenericKey shortcut. | 203 // keyWrap forces KeySplit to not take the GenericKey shortcut. |
190 k := keyWrap{mkKey("appid", "ns", "parent", 10, "renerd", "moo")
} | 204 k := keyWrap{mkKey("appid", "ns", "parent", 10, "renerd", "moo")
} |
191 » » aid, ns, toks := KeySplit(k) | 205 » » aid, ns, toks := Split(k) |
192 So(aid, ShouldEqual, "appid") | 206 So(aid, ShouldEqual, "appid") |
193 So(ns, ShouldEqual, "ns") | 207 So(ns, ShouldEqual, "ns") |
194 » » So(toks, ShouldResemble, []KeyTok{ | 208 » » So(toks, ShouldResemble, []ds.KeyTok{ |
195 {Kind: "parent", IntID: 10}, | 209 {Kind: "parent", IntID: 10}, |
196 {Kind: "renerd", StringID: "moo"}, | 210 {Kind: "renerd", StringID: "moo"}, |
197 }) | 211 }) |
198 }) | 212 }) |
199 | 213 |
200 Convey("KeySplit (nil)", t, func() { | 214 Convey("KeySplit (nil)", t, func() { |
201 » » aid, ns, toks := KeySplit(nil) | 215 » » aid, ns, toks := Split(nil) |
202 So(aid, ShouldEqual, "") | 216 So(aid, ShouldEqual, "") |
203 So(ns, ShouldEqual, "") | 217 So(ns, ShouldEqual, "") |
204 » » So(toks, ShouldResemble, []KeyTok(nil)) | 218 » » So(toks, ShouldResemble, []ds.KeyTok(nil)) |
205 }) | 219 }) |
206 | 220 |
207 Convey("KeySplit ((*GenericKey)(nil))", t, func() { | 221 Convey("KeySplit ((*GenericKey)(nil))", t, func() { |
208 » » aid, ns, toks := KeySplit((*GenericKey)(nil)) | 222 » » aid, ns, toks := Split((*Generic)(nil)) |
209 So(aid, ShouldEqual, "") | 223 So(aid, ShouldEqual, "") |
210 So(ns, ShouldEqual, "") | 224 So(ns, ShouldEqual, "") |
211 » » So(toks, ShouldResemble, []KeyTok(nil)) | 225 » » So(toks, ShouldResemble, []ds.KeyTok(nil)) |
212 }) | 226 }) |
213 | 227 |
214 Convey("KeysEqual", t, func() { | 228 Convey("KeysEqual", t, func() { |
215 k1 := mkKey("a", "n", "knd", 1) | 229 k1 := mkKey("a", "n", "knd", 1) |
216 k2 := mkKey("a", "n", "knd", 1) | 230 k2 := mkKey("a", "n", "knd", 1) |
217 » » So(KeysEqual(k1, k2), ShouldBeTrue) | 231 » » So(Equal(k1, k2), ShouldBeTrue) |
218 k3 := mkKey("a", "n", "knd", 2) | 232 k3 := mkKey("a", "n", "knd", 2) |
219 » » So(KeysEqual(k1, k3), ShouldBeFalse) | 233 » » So(Equal(k1, k3), ShouldBeFalse) |
220 }) | 234 }) |
221 | 235 |
222 Convey("KeyString", t, func() { | 236 Convey("KeyString", t, func() { |
223 k1 := mkKey("a", "n", "knd", 1, "other", "wat") | 237 k1 := mkKey("a", "n", "knd", 1, "other", "wat") |
224 » » So(KeyString(k1), ShouldEqual, "/knd,1/other,wat") | 238 » » So(String(k1), ShouldEqual, "/knd,1/other,wat") |
225 » » So(KeyString(nil), ShouldEqual, "") | 239 » » So(String(nil), ShouldEqual, "") |
226 }) | 240 }) |
227 | 241 |
228 Convey("*GenericKey supports json encoding", t, func() { | 242 Convey("*GenericKey supports json encoding", t, func() { |
229 type TestStruct struct { | 243 type TestStruct struct { |
230 » » » Key *GenericKey | 244 » » » Key *Generic |
231 } | 245 } |
232 t := &TestStruct{ | 246 t := &TestStruct{ |
233 » » » NewKey("aid", "ns", "kind", "id", 0, | 247 » » » New("aid", "ns", "kind", "id", 0, |
234 » » » » NewKey("aid", "ns", "parent", "", 1, nil), | 248 » » » » New("aid", "ns", "parent", "", 1, nil), |
235 )} | 249 )} |
236 d, err := json.Marshal(t) | 250 d, err := json.Marshal(t) |
237 So(err, ShouldBeNil) | 251 So(err, ShouldBeNil) |
238 t2 := &TestStruct{} | 252 t2 := &TestStruct{} |
239 err = json.Unmarshal(d, t2) | 253 err = json.Unmarshal(d, t2) |
240 So(err, ShouldBeNil) | 254 So(err, ShouldBeNil) |
241 So(t, ShouldResemble, t2) | 255 So(t, ShouldResemble, t2) |
242 }) | 256 }) |
243 } | 257 } |
OLD | NEW |