| 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 |