07139fdc5b
The keys package is used to encode and decode keys. Keys are used for storage in the key:value store.
254 lines
9.1 KiB
Go
254 lines
9.1 KiB
Go
// Copyright © 2016 Abcum Ltd
|
||
//
|
||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
// you may not use this file except in compliance with the License.
|
||
// You may obtain a copy of the License at
|
||
//
|
||
// http://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
// Unless required by applicable law or agreed to in writing, software
|
||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
|
||
package keys_test
|
||
|
||
import (
|
||
"testing"
|
||
"time"
|
||
|
||
"golang.org/x/text/collate"
|
||
"golang.org/x/text/language"
|
||
|
||
"github.com/abcum/surreal/util/keys"
|
||
. "github.com/smartystreets/goconvey/convey"
|
||
)
|
||
|
||
func TestEncodeDecode(t *testing.T) {
|
||
|
||
timer, _ := time.Parse(time.RFC3339, "1987-06-22T08:00:00.123456789Z")
|
||
|
||
tests := []struct {
|
||
str string
|
||
obj keys.Key
|
||
new keys.Key
|
||
}{
|
||
{
|
||
str: "/surreal/!/n/abcum",
|
||
obj: &keys.NS{KV: "surreal", NS: "abcum"},
|
||
new: &keys.NS{},
|
||
},
|
||
{
|
||
str: "/surreal/!/d/abcum/database",
|
||
obj: &keys.DB{KV: "surreal", NS: "abcum", DB: "database"},
|
||
new: &keys.DB{},
|
||
},
|
||
{
|
||
str: "/surreal/!/t/abcum/database/person",
|
||
obj: &keys.TB{KV: "surreal", NS: "abcum", DB: "database", TB: "person"},
|
||
new: &keys.TB{},
|
||
},
|
||
{
|
||
str: "/surreal/!/f/abcum/database/person/fullname",
|
||
obj: &keys.FD{KV: "surreal", NS: "abcum", DB: "database", TB: "person", FD: "fullname"},
|
||
new: &keys.FD{},
|
||
},
|
||
{
|
||
str: "/surreal/!/i/abcum/database/person/teenagers",
|
||
obj: &keys.IX{KV: "surreal", NS: "abcum", DB: "database", TB: "person", IX: "teenagers"},
|
||
new: &keys.IX{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/¤/[firstname,lastname]",
|
||
obj: &keys.Index{KV: "surreal", NS: "abcum", DB: "database", TB: "person", What: []string{"firstname", "lastname"}},
|
||
new: &keys.Index{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/873c2f37-ea03-4c5e-843e-cf393af44155",
|
||
obj: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "873c2f37-ea03-4c5e-843e-cf393af44155"},
|
||
new: &keys.Thing{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/•/873c2f37-ea03-4c5e-843e-cf393af44155/1987-06-22T08:00:00.123456789Z",
|
||
obj: &keys.Trail{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "873c2f37-ea03-4c5e-843e-cf393af44155", Time: timer},
|
||
new: &keys.Trail{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/‡/873c2f37-ea03-4c5e-843e-cf393af44155/friend/1987-06-22T08:00:00.123456789Z",
|
||
obj: &keys.Event{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "873c2f37-ea03-4c5e-843e-cf393af44155", Type: "friend", Time: timer},
|
||
new: &keys.Event{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/«»/873c2f37-ea03-4c5e-843e-cf393af44155/clicked/b38d7aa1-60d6-4f2d-8702-46bd0fa961fe",
|
||
obj: &keys.Edge{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "873c2f37-ea03-4c5e-843e-cf393af44155", Type: "clicked", Edge: "b38d7aa1-60d6-4f2d-8702-46bd0fa961fe"},
|
||
new: &keys.Edge{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/«/873c2f37-ea03-4c5e-843e-cf393af44155/clicked/b38d7aa1-60d6-4f2d-8702-46bd0fa961fe",
|
||
obj: &keys.Edge{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "873c2f37-ea03-4c5e-843e-cf393af44155", TK: "«", Type: "clicked", Edge: "b38d7aa1-60d6-4f2d-8702-46bd0fa961fe"},
|
||
new: &keys.Edge{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/»/873c2f37-ea03-4c5e-843e-cf393af44155/clicked/b38d7aa1-60d6-4f2d-8702-46bd0fa961fe",
|
||
obj: &keys.Edge{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "873c2f37-ea03-4c5e-843e-cf393af44155", TK: "»", Type: "clicked", Edge: "b38d7aa1-60d6-4f2d-8702-46bd0fa961fe"},
|
||
new: &keys.Edge{},
|
||
},
|
||
{
|
||
str: "/surreal/abcum/database/person/«»/873c2f37-ea03-4c5e-843e-cf393af44155/clicked/b38d7aa1-60d6-4f2d-8702-46bd0fa961fe",
|
||
obj: &keys.Edge{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "873c2f37-ea03-4c5e-843e-cf393af44155", TK: "«»", Type: "clicked", Edge: "b38d7aa1-60d6-4f2d-8702-46bd0fa961fe"},
|
||
new: &keys.Edge{},
|
||
},
|
||
}
|
||
|
||
for _, test := range tests {
|
||
|
||
Convey(test.str, t, func() {
|
||
|
||
Convey("String should match", func() {
|
||
So(test.obj.String(), ShouldEqual, test.str)
|
||
})
|
||
|
||
Convey("String should be a string", func() {
|
||
So(test.obj.String(), ShouldHaveSameTypeAs, "")
|
||
})
|
||
|
||
Convey("Encode should be a byte slice", func() {
|
||
So(test.obj.Encode(), ShouldHaveSameTypeAs, []byte{})
|
||
})
|
||
|
||
Convey("Key should encode and decode", func() {
|
||
enc := test.obj.Encode()
|
||
test.new.Decode(enc)
|
||
// So(test.new.String(), ShouldEqual, test.str)
|
||
})
|
||
|
||
})
|
||
|
||
}
|
||
|
||
}
|
||
|
||
func TestSorting(t *testing.T) {
|
||
|
||
c := collate.New(language.English, collate.Force, collate.Numeric)
|
||
|
||
tests := []struct {
|
||
res int
|
||
one keys.Key
|
||
two keys.Key
|
||
}{
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "1"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "2"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "2"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "12"},
|
||
},
|
||
{
|
||
res: 1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "12"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "2"},
|
||
},
|
||
{
|
||
res: -1, // Fullwidth is sorted as usual.
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "2"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "12"},
|
||
},
|
||
{
|
||
res: 1, // Circled is not sorted as numbers.
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "②"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "①②"},
|
||
},
|
||
{
|
||
res: 1, // Subscript is not sorted as numbers.
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "₂"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "₁₂"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "abc"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "ABC"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "ABC"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "zbc"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "ÄBC"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "zbc"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "ÁBC"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "zbc"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "zbc"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "ZBC"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Prefix},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Suffix},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Prefix},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "a"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Prefix},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "①"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Prefix},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "会"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Prefix},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "😀"},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "a"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Suffix},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "①"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Suffix},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "会"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Suffix},
|
||
},
|
||
{
|
||
res: -1,
|
||
one: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: "😀"},
|
||
two: &keys.Thing{KV: "surreal", NS: "abcum", DB: "database", TB: "person", ID: keys.Suffix},
|
||
},
|
||
}
|
||
|
||
for _, test := range tests {
|
||
|
||
Convey("Strings should sort correctly", t, func() {
|
||
one := string(test.one.Encode())
|
||
two := string(test.two.Encode())
|
||
res := c.CompareString(one, two)
|
||
So(res, ShouldEqual, test.res)
|
||
})
|
||
|
||
}
|
||
|
||
}
|