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