OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 package helper | |
6 | |
7 import ( | |
8 "encoding/json" | |
9 "fmt" | |
10 "testing" | |
11 | |
12 "github.com/luci/gae" | |
13 . "github.com/smartystreets/goconvey/convey" | |
14 ) | |
15 | |
16 func mkKey(aid, ns string, elems ...interface{}) gae.DSKey { | |
17 if len(elems)%2 != 0 { | |
18 panic("odd number of tokens") | |
19 } | |
20 toks := make([]gae.DSKeyTok, len(elems)/2) | |
21 for i := 0; i < len(elems); i += 2 { | |
22 toks[i/2].Kind = elems[i].(string) | |
23 switch x := elems[i+1].(type) { | |
24 case string: | |
25 toks[i/2].StringID = x | |
26 case int: | |
27 toks[i/2].IntID = int64(x) | |
28 default: | |
29 panic("bad token id") | |
30 } | |
31 } | |
32 return NewDSKeyToks(aid, ns, toks) | |
33 } | |
34 | |
35 func ShouldEqualKey(actual interface{}, expected ...interface{}) string { | |
36 if len(expected) != 1 { | |
37 return fmt.Sprintf("Assertion requires 1 expected value, got %d"
, len(expected)) | |
38 } | |
39 if DSKeysEqual(actual.(gae.DSKey), expected[0].(gae.DSKey)) { | |
40 return "" | |
41 } | |
42 return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0]) | |
43 } | |
44 | |
45 func TestKeyEncode(t *testing.T) { | |
46 t.Parallel() | |
47 | |
48 keys := []gae.DSKey{ | |
49 mkKey("appid", "ns", "kind", 1), | |
50 mkKey("appid", "ns", "nerd", "moo"), | |
51 mkKey("appid", "ns", "parent", 10, "renerd", "moo"), | |
52 } | |
53 | |
54 Convey("DSKey Round trip", t, func() { | |
55 for _, k := range keys { | |
56 k := k | |
57 Convey(k.String(), func() { | |
58 enc := DSKeyEncode(k) | |
59 aid, ns, toks, err := DSKeyToksDecode(enc) | |
60 So(err, ShouldBeNil) | |
61 dec := NewDSKeyToks(aid, ns, toks) | |
62 So(dec, ShouldNotBeNil) | |
63 So(dec, ShouldEqualKey, k) | |
64 | |
65 dec2, err := NewDSKeyFromEncoded(enc) | |
66 So(err, ShouldBeNil) | |
67 So(dec2, ShouldEqualKey, dec) | |
68 So(dec2, ShouldEqualKey, k) | |
69 }) | |
70 | |
71 Convey(k.String()+" (json)", func() { | |
72 data, err := DSKeyMarshalJSON(k) | |
73 So(err, ShouldBeNil) | |
74 | |
75 aid, ns, toks, err := DSKeyUnmarshalJSON(data) | |
76 So(err, ShouldBeNil) | |
77 So(NewDSKeyToks(aid, ns, toks), ShouldEqualKey,
k) | |
78 }) | |
79 } | |
80 }) | |
81 | |
82 Convey("NewDSKey", t, func() { | |
83 Convey("single", func() { | |
84 k := NewDSKey("appid", "ns", "kind", "", 1, nil) | |
85 So(k, ShouldEqualKey, keys[0]) | |
86 }) | |
87 | |
88 Convey("nest", func() { | |
89 k := NewDSKey("appid", "ns", "renerd", "moo", 0, | |
90 NewDSKey("appid", "ns", "parent", "", 10, nil)) | |
91 So(k, ShouldEqualKey, keys[2]) | |
92 }) | |
93 }) | |
94 | |
95 Convey("DSKey bad encoding", t, func() { | |
96 Convey("extra junk before", func() { | |
97 enc := DSKeyEncode(keys[2]) | |
98 _, _, _, err := DSKeyToksDecode("/" + enc) | |
99 So(err, ShouldErrLike, "illegal base64") | |
100 }) | |
101 | |
102 Convey("extra junk after", func() { | |
103 enc := DSKeyEncode(keys[2]) | |
104 _, _, _, err := DSKeyToksDecode(enc[:len(enc)-1]) | |
105 So(err, ShouldErrLike, "EOF") | |
106 }) | |
107 | |
108 Convey("json encoding includes quotes", func() { | |
109 data, err := DSKeyMarshalJSON(keys[0]) | |
110 So(err, ShouldBeNil) | |
111 | |
112 _, _, _, err = DSKeyUnmarshalJSON(append(data, '!')) | |
113 So(err, ShouldErrLike, "bad JSON key") | |
114 }) | |
115 }) | |
116 } | |
117 | |
118 type dumbKey1 struct{ gae.DSKey } | |
119 | |
120 func (dk dumbKey1) Namespace() string { return "ns" } | |
121 func (dk dumbKey1) Parent() gae.DSKey { return dk.DSKey } | |
122 func (dk dumbKey1) String() string { return "dumbKey1" } | |
123 | |
124 type dumbKey2 struct{ gae.DSKey } | |
125 | |
126 /// This is the dumb part... can't have both IDs set. | |
127 func (dk dumbKey2) IntID() int64 { return 1 } | |
128 func (dk dumbKey2) StringID() string { return "wat" } | |
129 | |
130 func (dk dumbKey2) Kind() string { return "kind" } | |
131 func (dk dumbKey2) Parent() gae.DSKey { return nil } | |
132 func (dk dumbKey2) Namespace() string { return "ns" } | |
133 func (dk dumbKey2) AppID() string { return "aid" } | |
134 func (dk dumbKey2) String() string { return "dumbKey2" } | |
135 | |
136 func TestBadKeyEncode(t *testing.T) { | |
137 t.Parallel() | |
138 | |
139 Convey("bad keys", t, func() { | |
140 Convey("incomplete", func() { | |
141 So(DSKeyIncomplete(mkKey("aid", "ns", "kind", 1)), Shoul
dBeFalse) | |
142 So(DSKeyIncomplete(mkKey("aid", "ns", "kind", 0)), Shoul
dBeTrue) | |
143 }) | |
144 | |
145 Convey("invalid", func() { | |
146 So(DSKeyValid(mkKey("aid", "ns", "hat", "face", "__kind_
_", 1), "ns", true), ShouldBeTrue) | |
147 So(DSKeyValid(mkKey("aid", "ns", "hat", "face", "kind",
1), "wat", false), ShouldBeFalse) | |
148 | |
149 bads := []gae.DSKey{ | |
150 nil, | |
151 mkKey("", "ns", "hat", "face"), | |
152 mkKey("aid", "ns", "base", 1, "", "id"), | |
153 mkKey("aid", "ns", "hat", "face", "__kind__", 1)
, | |
154 mkKey("aid", "ns", "hat", 0, "kind", 1), | |
155 dumbKey1{mkKey("aid", "badNS", "hat", 1)}, | |
156 dumbKey2{}, | |
157 } | |
158 for _, k := range bads { | |
159 s := "<nil>" | |
160 if k != nil { | |
161 s = k.String() | |
162 } | |
163 Convey(s, func() { | |
164 So(DSKeyValid(k, "ns", false), ShouldBeF
alse) | |
165 }) | |
166 } | |
167 }) | |
168 }) | |
169 } | |
170 | |
171 type keyWrap struct{ gae.DSKey } | |
172 | |
173 func (k keyWrap) Parent() gae.DSKey { | |
174 if k.DSKey.Parent() != nil { | |
175 return keyWrap{k.DSKey.Parent()} | |
176 } | |
177 return nil | |
178 } | |
179 | |
180 func TestMiscKey(t *testing.T) { | |
181 t.Parallel() | |
182 | |
183 Convey("DSKeyRoot", t, func() { | |
184 k := mkKey("appid", "ns", "parent", 10, "renerd", "moo") | |
185 r := mkKey("appid", "ns", "parent", 10) | |
186 So(DSKeyRoot(k), ShouldEqualKey, r) | |
187 So(DSKeyRoot(nil), ShouldBeNil) | |
188 }) | |
189 | |
190 Convey("DSKeySplit", t, func() { | |
191 // keyWrap forces DSKeySplit to not take the GenericDSKey shortc
ut. | |
192 k := keyWrap{mkKey("appid", "ns", "parent", 10, "renerd", "moo")
} | |
193 aid, ns, toks := DSKeySplit(k) | |
194 So(aid, ShouldEqual, "appid") | |
195 So(ns, ShouldEqual, "ns") | |
196 So(toks, ShouldResemble, []gae.DSKeyTok{ | |
197 {Kind: "parent", IntID: 10}, | |
198 {Kind: "renerd", StringID: "moo"}, | |
199 }) | |
200 }) | |
201 | |
202 Convey("DSKeySplit (nil)", t, func() { | |
203 aid, ns, toks := DSKeySplit(nil) | |
204 So(aid, ShouldEqual, "") | |
205 So(ns, ShouldEqual, "") | |
206 So(toks, ShouldResemble, []gae.DSKeyTok(nil)) | |
207 }) | |
208 | |
209 Convey("DSKeySplit ((*GenericDSKey)(nil))", t, func() { | |
210 aid, ns, toks := DSKeySplit((*GenericDSKey)(nil)) | |
211 So(aid, ShouldEqual, "") | |
212 So(ns, ShouldEqual, "") | |
213 So(toks, ShouldResemble, []gae.DSKeyTok(nil)) | |
214 }) | |
215 | |
216 Convey("DSKeysEqual", t, func() { | |
217 k1 := mkKey("a", "n", "knd", 1) | |
218 k2 := mkKey("a", "n", "knd", 1) | |
219 So(DSKeysEqual(k1, k2), ShouldBeTrue) | |
220 k3 := mkKey("a", "n", "knd", 2) | |
221 So(DSKeysEqual(k1, k3), ShouldBeFalse) | |
222 }) | |
223 | |
224 Convey("DSKeyString", t, func() { | |
225 k1 := mkKey("a", "n", "knd", 1, "other", "wat") | |
226 So(DSKeyString(k1), ShouldEqual, "/knd,1/other,wat") | |
227 So(DSKeyString(nil), ShouldEqual, "") | |
228 }) | |
229 | |
230 Convey("*GenericDSKey supports json encoding", t, func() { | |
231 type TestStruct struct { | |
232 Key *GenericDSKey | |
233 } | |
234 t := &TestStruct{ | |
235 NewDSKey("aid", "ns", "kind", "id", 0, | |
236 NewDSKey("aid", "ns", "parent", "", 1, nil), | |
237 )} | |
238 d, err := json.Marshal(t) | |
239 So(err, ShouldBeNil) | |
240 t2 := &TestStruct{} | |
241 err = json.Unmarshal(d, t2) | |
242 So(err, ShouldBeNil) | |
243 So(t, ShouldResemble, t2) | |
244 }) | |
245 } | |
OLD | NEW |