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 datastore |
| 6 |
| 7 import ( |
| 8 "encoding/json" |
| 9 "fmt" |
| 10 "testing" |
| 11 |
| 12 . "github.com/luci/luci-go/common/testing/assertions" |
| 13 . "github.com/smartystreets/goconvey/convey" |
| 14 ) |
| 15 |
| 16 func ShouldEqualKey(actual interface{}, expected ...interface{}) string { |
| 17 if len(expected) != 1 { |
| 18 return fmt.Sprintf("Assertion requires 1 expected value, got %d"
, len(expected)) |
| 19 } |
| 20 if actual.(*Key).Equal(expected[0].(*Key)) { |
| 21 return "" |
| 22 } |
| 23 return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0]) |
| 24 } |
| 25 |
| 26 func TestKeyEncode(t *testing.T) { |
| 27 t.Parallel() |
| 28 |
| 29 keys := []*Key{ |
| 30 MakeKey("appid", "ns", "kind", 1), |
| 31 MakeKey("appid", "ns", "nerd", "moo"), |
| 32 MakeKey("appid", "ns", "parent", 10, "renerd", "moo"), |
| 33 } |
| 34 |
| 35 Convey("Key Round trip", t, func() { |
| 36 for _, k := range keys { |
| 37 k := k |
| 38 Convey(k.String(), func() { |
| 39 enc := k.Encode() |
| 40 dec, err := NewKeyEncoded(enc) |
| 41 So(err, ShouldBeNil) |
| 42 So(dec, ShouldNotBeNil) |
| 43 So(dec, ShouldEqualKey, k) |
| 44 |
| 45 dec2, err := NewKeyEncoded(enc) |
| 46 So(err, ShouldBeNil) |
| 47 So(dec2, ShouldEqualKey, dec) |
| 48 So(dec2, ShouldEqualKey, k) |
| 49 }) |
| 50 |
| 51 Convey(k.String()+" (json)", func() { |
| 52 data, err := k.MarshalJSON() |
| 53 So(err, ShouldBeNil) |
| 54 |
| 55 dec := &Key{} |
| 56 So(dec.UnmarshalJSON(data), ShouldBeNil) |
| 57 So(dec, ShouldEqualKey, k) |
| 58 }) |
| 59 } |
| 60 }) |
| 61 |
| 62 Convey("NewKey", t, func() { |
| 63 Convey("single", func() { |
| 64 k := NewKey("appid", "ns", "kind", "", 1, nil) |
| 65 So(k, ShouldEqualKey, keys[0]) |
| 66 }) |
| 67 |
| 68 Convey("empty", func() { |
| 69 So(NewKeyToks("appid", "ns", nil), ShouldBeNil) |
| 70 }) |
| 71 |
| 72 Convey("nest", func() { |
| 73 k := NewKey("appid", "ns", "renerd", "moo", 0, |
| 74 NewKey("appid", "ns", "parent", "", 10, nil)) |
| 75 So(k, ShouldEqualKey, keys[2]) |
| 76 }) |
| 77 }) |
| 78 |
| 79 Convey("Key bad encoding", t, func() { |
| 80 Convey("extra junk before", func() { |
| 81 enc := keys[2].Encode() |
| 82 _, err := NewKeyEncoded("/" + enc) |
| 83 So(err, ShouldErrLike, "illegal base64") |
| 84 }) |
| 85 |
| 86 Convey("extra junk after", func() { |
| 87 enc := keys[2].Encode() |
| 88 _, err := NewKeyEncoded(enc[:len(enc)-1]) |
| 89 So(err, ShouldErrLike, "EOF") |
| 90 }) |
| 91 |
| 92 Convey("json encoding includes quotes", func() { |
| 93 data, err := keys[0].MarshalJSON() |
| 94 So(err, ShouldBeNil) |
| 95 |
| 96 dec := &Key{} |
| 97 err = dec.UnmarshalJSON(append(data, '!')) |
| 98 So(err, ShouldErrLike, "bad JSON key") |
| 99 }) |
| 100 }) |
| 101 } |
| 102 |
| 103 func TestKeyValidity(t *testing.T) { |
| 104 //t.Parallel() |
| 105 |
| 106 Convey("keys validity", t, func() { |
| 107 Convey("incomplete", func() { |
| 108 So(MakeKey("aid", "ns", "kind", 1).Incomplete(), ShouldB
eFalse) |
| 109 So(MakeKey("aid", "ns", "kind", 0).Incomplete(), ShouldB
eTrue) |
| 110 }) |
| 111 |
| 112 Convey("invalid", func() { |
| 113 So(MakeKey("aid", "ns", "hat", "face", "__kind__", 1).Va
lid(true, "aid", "ns"), ShouldBeTrue) |
| 114 |
| 115 bads := []*Key{ |
| 116 nil, |
| 117 NewKeyToks("aid", "ns", []KeyTok{{"Kind", 1, "1"
}}), |
| 118 MakeKey("", "ns", "hat", "face"), |
| 119 MakeKey("aid", "ns", "base", 1, "", "id"), |
| 120 MakeKey("aid", "ns", "hat", "face", "__kind__",
1), |
| 121 MakeKey("aid", "ns", "hat", 0, "kind", 1), |
| 122 } |
| 123 for _, k := range bads { |
| 124 s := "<nil>" |
| 125 if k != nil { |
| 126 s = k.String() |
| 127 } |
| 128 Convey(s, func() { |
| 129 So(k.Valid(false, "aid", "ns"), ShouldBe
False) |
| 130 }) |
| 131 } |
| 132 }) |
| 133 |
| 134 Convey("partially valid", func() { |
| 135 So(MakeKey("aid", "ns", "kind", "").PartialValid("aid",
"ns"), ShouldBeTrue) |
| 136 So(MakeKey("aid", "ns", "kind", "", "child", "").Partial
Valid("aid", "ns"), ShouldBeFalse) |
| 137 }) |
| 138 }) |
| 139 } |
| 140 |
| 141 func TestMiscKey(t *testing.T) { |
| 142 t.Parallel() |
| 143 |
| 144 Convey("KeyRoot", t, func() { |
| 145 k := MakeKey("appid", "ns", "parent", 10, "renerd", "moo") |
| 146 r := MakeKey("appid", "ns", "parent", 10) |
| 147 So(k.Root(), ShouldEqualKey, r) |
| 148 So((*Key)(nil).Root(), ShouldBeNil) |
| 149 }) |
| 150 |
| 151 Convey("KeySplit", t, func() { |
| 152 aid, ns, toks := (*Key)(nil).Split() |
| 153 So(aid, ShouldEqual, "") |
| 154 So(ns, ShouldEqual, "") |
| 155 So(toks, ShouldResemble, []KeyTok(nil)) |
| 156 }) |
| 157 |
| 158 Convey("KeysEqual", t, func() { |
| 159 k1 := MakeKey("a", "n", "knd", 1) |
| 160 k2 := MakeKey("a", "n", "knd", 1) |
| 161 So(k1.Equal(k2), ShouldBeTrue) |
| 162 k3 := MakeKey("a", "n", "knd", 2) |
| 163 So(k1.Equal(k3), ShouldBeFalse) |
| 164 }) |
| 165 |
| 166 Convey("KeyString", t, func() { |
| 167 k1 := MakeKey("a", "n", "knd", 1, "other", "wat") |
| 168 So(k1.String(), ShouldEqual, "a:n:/knd,1/other,\"wat\"") |
| 169 So((*Key)(nil).String(), ShouldEqual, "") |
| 170 }) |
| 171 |
| 172 Convey("*GenericKey supports json encoding", t, func() { |
| 173 type TestStruct struct { |
| 174 Key *Key |
| 175 } |
| 176 t := &TestStruct{ |
| 177 NewKey("aid", "ns", "kind", "id", 0, |
| 178 NewKey("aid", "ns", "parent", "", 1, nil), |
| 179 )} |
| 180 d, err := json.Marshal(t) |
| 181 So(err, ShouldBeNil) |
| 182 t2 := &TestStruct{} |
| 183 err = json.Unmarshal(d, t2) |
| 184 So(err, ShouldBeNil) |
| 185 So(t.Key, ShouldEqualKey, t2.Key) |
| 186 }) |
| 187 } |
| 188 |
| 189 func shouldBeLess(actual interface{}, expected ...interface{}) string { |
| 190 a, b := actual.(*Key), expected[0].(*Key) |
| 191 if a.Less(b) { |
| 192 return "" |
| 193 } |
| 194 return fmt.Sprintf("Expected %q < %q", a.String(), b.String()) |
| 195 } |
| 196 |
| 197 func shouldNotBeEqual(actual interface{}, expected ...interface{}) string { |
| 198 a, b := actual.(*Key), expected[0].(*Key) |
| 199 if !a.Equal(b) { |
| 200 return "" |
| 201 } |
| 202 return fmt.Sprintf("Expected %q != %q", a.String(), b.String()) |
| 203 } |
| 204 |
| 205 func shouldNotBeLess(actual interface{}, expected ...interface{}) string { |
| 206 a, b := actual.(*Key), expected[0].(*Key) |
| 207 if !a.Less(b) { |
| 208 return "" |
| 209 } |
| 210 return fmt.Sprintf("Expected !(%q < %q)", a.String(), b.String()) |
| 211 } |
| 212 |
| 213 func TestKeySort(t *testing.T) { |
| 214 t.Parallel() |
| 215 |
| 216 Convey("KeyTok.Less() works", t, func() { |
| 217 So((KeyTok{"a", 0, "1"}).Less(KeyTok{"b", 0, "2"}), ShouldBeTrue
) |
| 218 So((KeyTok{"b", 0, "1"}).Less(KeyTok{"a", 0, "2"}), ShouldBeFals
e) |
| 219 So((KeyTok{"kind", 0, "1"}).Less(KeyTok{"kind", 0, "2"}), Should
BeTrue) |
| 220 So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 2, ""}), ShouldBe
True) |
| 221 So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 0, "1"}), ShouldB
eTrue) |
| 222 }) |
| 223 |
| 224 Convey("Key comparison works", t, func() { |
| 225 So((*Key)(nil).Equal(nil), ShouldBeTrue) |
| 226 |
| 227 s := []*Key{ |
| 228 nil, |
| 229 MakeKey("A", "", "kind", 1), |
| 230 MakeKey("A", "n", "kind", 1), |
| 231 MakeKey("A", "n", "kind", 1, "something", "else"), |
| 232 MakeKey("A", "n", "kind", "1"), |
| 233 MakeKey("A", "n", "kind", "1", "something", "else"), |
| 234 MakeKey("A", "n", "other", 1, "something", "else"), |
| 235 MakeKey("a", "", "kind", 1), |
| 236 MakeKey("a", "n", "kind", 1), |
| 237 MakeKey("a", "n", "kind", 2), |
| 238 MakeKey("a", "p", "aleph", 1), |
| 239 MakeKey("b", "n", "kind", 2), |
| 240 } |
| 241 |
| 242 for i := 1; i < len(s); i++ { |
| 243 So(s[i-1], shouldBeLess, s[i]) |
| 244 So(s[i-1], shouldNotBeEqual, s[i]) |
| 245 So(s[i], shouldNotBeEqual, s[i-1]) |
| 246 So(s[i], shouldNotBeLess, s[i-1]) |
| 247 } |
| 248 }) |
| 249 } |
OLD | NEW |