| Index: service/datastore/key_test.go
|
| diff --git a/service/datastore/key_test.go b/service/datastore/key_test.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b7f964fd1b866efe083ac5c25085b65f7c69c1a6
|
| --- /dev/null
|
| +++ b/service/datastore/key_test.go
|
| @@ -0,0 +1,249 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package datastore
|
| +
|
| +import (
|
| + "encoding/json"
|
| + "fmt"
|
| + "testing"
|
| +
|
| + . "github.com/luci/luci-go/common/testing/assertions"
|
| + . "github.com/smartystreets/goconvey/convey"
|
| +)
|
| +
|
| +func ShouldEqualKey(actual interface{}, expected ...interface{}) string {
|
| + if len(expected) != 1 {
|
| + return fmt.Sprintf("Assertion requires 1 expected value, got %d", len(expected))
|
| + }
|
| + if actual.(*Key).Equal(expected[0].(*Key)) {
|
| + return ""
|
| + }
|
| + return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0])
|
| +}
|
| +
|
| +func TestKeyEncode(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + keys := []*Key{
|
| + MakeKey("appid", "ns", "kind", 1),
|
| + MakeKey("appid", "ns", "nerd", "moo"),
|
| + MakeKey("appid", "ns", "parent", 10, "renerd", "moo"),
|
| + }
|
| +
|
| + Convey("Key Round trip", t, func() {
|
| + for _, k := range keys {
|
| + k := k
|
| + Convey(k.String(), func() {
|
| + enc := k.Encode()
|
| + dec, err := NewKeyEncoded(enc)
|
| + So(err, ShouldBeNil)
|
| + So(dec, ShouldNotBeNil)
|
| + So(dec, ShouldEqualKey, k)
|
| +
|
| + dec2, err := NewKeyEncoded(enc)
|
| + So(err, ShouldBeNil)
|
| + So(dec2, ShouldEqualKey, dec)
|
| + So(dec2, ShouldEqualKey, k)
|
| + })
|
| +
|
| + Convey(k.String()+" (json)", func() {
|
| + data, err := k.MarshalJSON()
|
| + So(err, ShouldBeNil)
|
| +
|
| + dec := &Key{}
|
| + So(dec.UnmarshalJSON(data), ShouldBeNil)
|
| + So(dec, ShouldEqualKey, k)
|
| + })
|
| + }
|
| + })
|
| +
|
| + Convey("NewKey", t, func() {
|
| + Convey("single", func() {
|
| + k := NewKey("appid", "ns", "kind", "", 1, nil)
|
| + So(k, ShouldEqualKey, keys[0])
|
| + })
|
| +
|
| + Convey("empty", func() {
|
| + So(NewKeyToks("appid", "ns", nil), ShouldBeNil)
|
| + })
|
| +
|
| + Convey("nest", func() {
|
| + k := NewKey("appid", "ns", "renerd", "moo", 0,
|
| + NewKey("appid", "ns", "parent", "", 10, nil))
|
| + So(k, ShouldEqualKey, keys[2])
|
| + })
|
| + })
|
| +
|
| + Convey("Key bad encoding", t, func() {
|
| + Convey("extra junk before", func() {
|
| + enc := keys[2].Encode()
|
| + _, err := NewKeyEncoded("/" + enc)
|
| + So(err, ShouldErrLike, "illegal base64")
|
| + })
|
| +
|
| + Convey("extra junk after", func() {
|
| + enc := keys[2].Encode()
|
| + _, err := NewKeyEncoded(enc[:len(enc)-1])
|
| + So(err, ShouldErrLike, "EOF")
|
| + })
|
| +
|
| + Convey("json encoding includes quotes", func() {
|
| + data, err := keys[0].MarshalJSON()
|
| + So(err, ShouldBeNil)
|
| +
|
| + dec := &Key{}
|
| + err = dec.UnmarshalJSON(append(data, '!'))
|
| + So(err, ShouldErrLike, "bad JSON key")
|
| + })
|
| + })
|
| +}
|
| +
|
| +func TestKeyValidity(t *testing.T) {
|
| + //t.Parallel()
|
| +
|
| + Convey("keys validity", t, func() {
|
| + Convey("incomplete", func() {
|
| + So(MakeKey("aid", "ns", "kind", 1).Incomplete(), ShouldBeFalse)
|
| + So(MakeKey("aid", "ns", "kind", 0).Incomplete(), ShouldBeTrue)
|
| + })
|
| +
|
| + Convey("invalid", func() {
|
| + So(MakeKey("aid", "ns", "hat", "face", "__kind__", 1).Valid(true, "aid", "ns"), ShouldBeTrue)
|
| +
|
| + bads := []*Key{
|
| + nil,
|
| + NewKeyToks("aid", "ns", []KeyTok{{"Kind", 1, "1"}}),
|
| + MakeKey("", "ns", "hat", "face"),
|
| + MakeKey("aid", "ns", "base", 1, "", "id"),
|
| + MakeKey("aid", "ns", "hat", "face", "__kind__", 1),
|
| + MakeKey("aid", "ns", "hat", 0, "kind", 1),
|
| + }
|
| + for _, k := range bads {
|
| + s := "<nil>"
|
| + if k != nil {
|
| + s = k.String()
|
| + }
|
| + Convey(s, func() {
|
| + So(k.Valid(false, "aid", "ns"), ShouldBeFalse)
|
| + })
|
| + }
|
| + })
|
| +
|
| + Convey("partially valid", func() {
|
| + So(MakeKey("aid", "ns", "kind", "").PartialValid("aid", "ns"), ShouldBeTrue)
|
| + So(MakeKey("aid", "ns", "kind", "", "child", "").PartialValid("aid", "ns"), ShouldBeFalse)
|
| + })
|
| + })
|
| +}
|
| +
|
| +func TestMiscKey(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + Convey("KeyRoot", t, func() {
|
| + k := MakeKey("appid", "ns", "parent", 10, "renerd", "moo")
|
| + r := MakeKey("appid", "ns", "parent", 10)
|
| + So(k.Root(), ShouldEqualKey, r)
|
| + So((*Key)(nil).Root(), ShouldBeNil)
|
| + })
|
| +
|
| + Convey("KeySplit", t, func() {
|
| + aid, ns, toks := (*Key)(nil).Split()
|
| + So(aid, ShouldEqual, "")
|
| + So(ns, ShouldEqual, "")
|
| + So(toks, ShouldResemble, []KeyTok(nil))
|
| + })
|
| +
|
| + Convey("KeysEqual", t, func() {
|
| + k1 := MakeKey("a", "n", "knd", 1)
|
| + k2 := MakeKey("a", "n", "knd", 1)
|
| + So(k1.Equal(k2), ShouldBeTrue)
|
| + k3 := MakeKey("a", "n", "knd", 2)
|
| + So(k1.Equal(k3), ShouldBeFalse)
|
| + })
|
| +
|
| + Convey("KeyString", t, func() {
|
| + k1 := MakeKey("a", "n", "knd", 1, "other", "wat")
|
| + So(k1.String(), ShouldEqual, "a:n:/knd,1/other,\"wat\"")
|
| + So((*Key)(nil).String(), ShouldEqual, "")
|
| + })
|
| +
|
| + Convey("*GenericKey supports json encoding", t, func() {
|
| + type TestStruct struct {
|
| + Key *Key
|
| + }
|
| + t := &TestStruct{
|
| + NewKey("aid", "ns", "kind", "id", 0,
|
| + NewKey("aid", "ns", "parent", "", 1, nil),
|
| + )}
|
| + d, err := json.Marshal(t)
|
| + So(err, ShouldBeNil)
|
| + t2 := &TestStruct{}
|
| + err = json.Unmarshal(d, t2)
|
| + So(err, ShouldBeNil)
|
| + So(t.Key, ShouldEqualKey, t2.Key)
|
| + })
|
| +}
|
| +
|
| +func shouldBeLess(actual interface{}, expected ...interface{}) string {
|
| + a, b := actual.(*Key), expected[0].(*Key)
|
| + if a.Less(b) {
|
| + return ""
|
| + }
|
| + return fmt.Sprintf("Expected %q < %q", a.String(), b.String())
|
| +}
|
| +
|
| +func shouldNotBeEqual(actual interface{}, expected ...interface{}) string {
|
| + a, b := actual.(*Key), expected[0].(*Key)
|
| + if !a.Equal(b) {
|
| + return ""
|
| + }
|
| + return fmt.Sprintf("Expected %q != %q", a.String(), b.String())
|
| +}
|
| +
|
| +func shouldNotBeLess(actual interface{}, expected ...interface{}) string {
|
| + a, b := actual.(*Key), expected[0].(*Key)
|
| + if !a.Less(b) {
|
| + return ""
|
| + }
|
| + return fmt.Sprintf("Expected !(%q < %q)", a.String(), b.String())
|
| +}
|
| +
|
| +func TestKeySort(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + Convey("KeyTok.Less() works", t, func() {
|
| + So((KeyTok{"a", 0, "1"}).Less(KeyTok{"b", 0, "2"}), ShouldBeTrue)
|
| + So((KeyTok{"b", 0, "1"}).Less(KeyTok{"a", 0, "2"}), ShouldBeFalse)
|
| + So((KeyTok{"kind", 0, "1"}).Less(KeyTok{"kind", 0, "2"}), ShouldBeTrue)
|
| + So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 2, ""}), ShouldBeTrue)
|
| + So((KeyTok{"kind", 1, ""}).Less(KeyTok{"kind", 0, "1"}), ShouldBeTrue)
|
| + })
|
| +
|
| + Convey("Key comparison works", t, func() {
|
| + So((*Key)(nil).Equal(nil), ShouldBeTrue)
|
| +
|
| + s := []*Key{
|
| + nil,
|
| + MakeKey("A", "", "kind", 1),
|
| + MakeKey("A", "n", "kind", 1),
|
| + MakeKey("A", "n", "kind", 1, "something", "else"),
|
| + MakeKey("A", "n", "kind", "1"),
|
| + MakeKey("A", "n", "kind", "1", "something", "else"),
|
| + MakeKey("A", "n", "other", 1, "something", "else"),
|
| + MakeKey("a", "", "kind", 1),
|
| + MakeKey("a", "n", "kind", 1),
|
| + MakeKey("a", "n", "kind", 2),
|
| + MakeKey("a", "p", "aleph", 1),
|
| + MakeKey("b", "n", "kind", 2),
|
| + }
|
| +
|
| + for i := 1; i < len(s); i++ {
|
| + So(s[i-1], shouldBeLess, s[i])
|
| + So(s[i-1], shouldNotBeEqual, s[i])
|
| + So(s[i], shouldNotBeEqual, s[i-1])
|
| + So(s[i], shouldNotBeLess, s[i-1])
|
| + }
|
| + })
|
| +}
|
|
|