blob: 32b67b454df02e8f6f1e93389632ff59d0c0d71d [file] [log] [blame]
/*
Copyright 2017 Google LLC
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 spanner
import (
"testing"
"time"
"cloud.google.com/go/civil"
proto3 "github.com/golang/protobuf/ptypes/struct"
sppb "google.golang.org/genproto/googleapis/spanner/v1"
)
// Test Key.String() and Key.proto().
func TestKey(t *testing.T) {
tm, _ := time.Parse(time.RFC3339Nano, "2016-11-15T15:04:05.999999999Z")
dt, _ := civil.ParseDate("2016-11-15")
for _, test := range []struct {
k Key
wantProto *proto3.ListValue
wantStr string
}{
{
k: Key{int(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{int8(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{int16(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{int32(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{int64(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{uint8(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{uint16(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{uint32(1)},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{true},
wantProto: listValueProto(boolProto(true)),
wantStr: "(true)",
},
{
k: Key{float32(1.5)},
wantProto: listValueProto(floatProto(1.5)),
wantStr: "(1.5)",
},
{
k: Key{float64(1.5)},
wantProto: listValueProto(floatProto(1.5)),
wantStr: "(1.5)",
},
{
k: Key{"value"},
wantProto: listValueProto(stringProto("value")),
wantStr: `("value")`,
},
{
k: Key{[]byte(nil)},
wantProto: listValueProto(nullProto()),
wantStr: "(<null>)",
},
{
k: Key{[]byte{}},
wantProto: listValueProto(stringProto("")),
wantStr: `("")`,
},
{
k: Key{tm},
wantProto: listValueProto(stringProto("2016-11-15T15:04:05.999999999Z")),
wantStr: `("2016-11-15T15:04:05.999999999Z")`,
},
{k: Key{dt},
wantProto: listValueProto(stringProto("2016-11-15")),
wantStr: `("2016-11-15")`,
},
{
k: Key{[]byte("value")},
wantProto: listValueProto(bytesProto([]byte("value"))),
wantStr: `("value")`,
},
{
k: Key{NullInt64{1, true}},
wantProto: listValueProto(stringProto("1")),
wantStr: "(1)",
},
{
k: Key{NullInt64{2, false}},
wantProto: listValueProto(nullProto()),
wantStr: "(<null>)",
},
{
k: Key{NullFloat64{1.5, true}},
wantProto: listValueProto(floatProto(1.5)),
wantStr: "(1.5)",
},
{
k: Key{NullFloat64{2.0, false}},
wantProto: listValueProto(nullProto()),
wantStr: "(<null>)",
},
{
k: Key{NullBool{true, true}},
wantProto: listValueProto(boolProto(true)),
wantStr: "(true)",
},
{
k: Key{NullBool{true, false}},
wantProto: listValueProto(nullProto()),
wantStr: "(<null>)",
},
{
k: Key{NullString{"value", true}},
wantProto: listValueProto(stringProto("value")),
wantStr: `("value")`,
},
{
k: Key{NullString{"value", false}},
wantProto: listValueProto(nullProto()),
wantStr: "(<null>)",
},
{
k: Key{NullTime{tm, true}},
wantProto: listValueProto(timeProto(tm)),
wantStr: `("2016-11-15T15:04:05.999999999Z")`,
},
{
k: Key{NullTime{time.Now(), false}},
wantProto: listValueProto(nullProto()),
wantStr: "(<null>)",
},
{
k: Key{NullDate{dt, true}},
wantProto: listValueProto(dateProto(dt)),
wantStr: `("2016-11-15")`,
},
{
k: Key{NullDate{civil.Date{}, false}},
wantProto: listValueProto(nullProto()),
wantStr: "(<null>)",
},
{
k: Key{int(1), NullString{"value", false}, "value", 1.5, true},
wantProto: listValueProto(stringProto("1"), nullProto(), stringProto("value"), floatProto(1.5), boolProto(true)),
wantStr: `(1,<null>,"value",1.5,true)`,
},
} {
if got := test.k.String(); got != test.wantStr {
t.Errorf("%v.String() = %v, want %v", test.k, got, test.wantStr)
}
gotProto, err := test.k.proto()
if err != nil {
t.Errorf("%v.proto() returns error %v; want nil error", test.k, err)
}
if !testEqual(gotProto, test.wantProto) {
t.Errorf("%v.proto() = \n%v\nwant:\n%v", test.k, gotProto, test.wantProto)
}
}
}
// Test KeyRange.String() and KeyRange.proto().
func TestKeyRange(t *testing.T) {
for _, test := range []struct {
kr KeyRange
wantProto *sppb.KeyRange
wantStr string
}{
{
kr: KeyRange{Key{"A"}, Key{"D"}, OpenOpen},
wantProto: &sppb.KeyRange{
StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(stringProto("A"))},
EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(stringProto("D"))},
},
wantStr: `(("A"),("D"))`,
},
{
kr: KeyRange{Key{1}, Key{10}, OpenClosed},
wantProto: &sppb.KeyRange{
StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(stringProto("1"))},
EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(stringProto("10"))},
},
wantStr: "((1),(10)]",
},
{
kr: KeyRange{Key{1.5, 2.1, 0.2}, Key{1.9, 0.7}, ClosedOpen},
wantProto: &sppb.KeyRange{
StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(floatProto(1.5), floatProto(2.1), floatProto(0.2))},
EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(floatProto(1.9), floatProto(0.7))},
},
wantStr: "[(1.5,2.1,0.2),(1.9,0.7))",
},
{
kr: KeyRange{Key{NullInt64{1, true}}, Key{10}, ClosedClosed},
wantProto: &sppb.KeyRange{
StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(stringProto("1"))},
EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(stringProto("10"))},
},
wantStr: "[(1),(10)]",
},
} {
if got := test.kr.String(); got != test.wantStr {
t.Errorf("%v.String() = %v, want %v", test.kr, got, test.wantStr)
}
gotProto, err := test.kr.proto()
if err != nil {
t.Errorf("%v.proto() returns error %v; want nil error", test.kr, err)
}
if !testEqual(gotProto, test.wantProto) {
t.Errorf("%v.proto() = \n%v\nwant:\n%v", test.kr, gotProto.String(), test.wantProto.String())
}
}
}
func TestPrefixRange(t *testing.T) {
got := Key{1}.AsPrefix()
want := KeyRange{Start: Key{1}, End: Key{1}, Kind: ClosedClosed}
if !testEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
}
func TestKeySets(t *testing.T) {
int1 := intProto(1)
int2 := intProto(2)
int3 := intProto(3)
int4 := intProto(4)
for i, test := range []struct {
ks KeySet
wantProto *sppb.KeySet
}{
{
KeySets(),
&sppb.KeySet{},
},
{
Key{4},
&sppb.KeySet{
Keys: []*proto3.ListValue{listValueProto(int4)},
},
},
{
AllKeys(),
&sppb.KeySet{All: true},
},
{
KeySets(Key{1, 2}, Key{3, 4}),
&sppb.KeySet{
Keys: []*proto3.ListValue{
listValueProto(int1, int2),
listValueProto(int3, int4),
},
},
},
{
KeyRange{Key{1}, Key{2}, ClosedOpen},
&sppb.KeySet{Ranges: []*sppb.KeyRange{
{
StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int1)},
EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(int2)},
},
}},
},
{
Key{2}.AsPrefix(),
&sppb.KeySet{Ranges: []*sppb.KeyRange{
{
StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int2)},
EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int2)},
},
}},
},
{
KeySets(
KeyRange{Key{1}, Key{2}, ClosedClosed},
KeyRange{Key{3}, Key{4}, OpenClosed},
),
&sppb.KeySet{
Ranges: []*sppb.KeyRange{
{
StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int1)},
EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int2)},
},
{
StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(int3)},
EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int4)},
},
},
},
},
{
KeySets(
Key{1},
KeyRange{Key{2}, Key{3}, ClosedClosed},
KeyRange{Key{4}, Key{5}, OpenClosed},
KeySets(),
Key{6}),
&sppb.KeySet{
Keys: []*proto3.ListValue{
listValueProto(int1),
listValueProto(intProto(6)),
},
Ranges: []*sppb.KeyRange{
{
StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int2)},
EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int3)},
},
{
StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(int4)},
EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(intProto(5))},
},
},
},
},
{
KeySets(
Key{1},
KeyRange{Key{2}, Key{3}, ClosedClosed},
AllKeys(),
KeyRange{Key{4}, Key{5}, OpenClosed},
Key{6}),
&sppb.KeySet{All: true},
},
} {
gotProto, err := test.ks.keySetProto()
if err != nil {
t.Errorf("#%d: %v.proto() returns error %v; want nil error", i, test.ks, err)
}
if !testEqual(gotProto, test.wantProto) {
t.Errorf("#%d: %v.proto() = \n%v\nwant:\n%v", i, test.ks, gotProto.String(), test.wantProto.String())
}
}
}