1/* 2Copyright 2017 Google LLC 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package spanner 18 19import ( 20 "testing" 21 "time" 22 23 "cloud.google.com/go/civil" 24 proto3 "github.com/golang/protobuf/ptypes/struct" 25 sppb "google.golang.org/genproto/googleapis/spanner/v1" 26) 27 28// Test Key.String() and Key.proto(). 29func TestKey(t *testing.T) { 30 tm, _ := time.Parse(time.RFC3339Nano, "2016-11-15T15:04:05.999999999Z") 31 dt, _ := civil.ParseDate("2016-11-15") 32 for _, test := range []struct { 33 k Key 34 wantProto *proto3.ListValue 35 wantStr string 36 }{ 37 { 38 k: Key{int(1)}, 39 wantProto: listValueProto(stringProto("1")), 40 wantStr: "(1)", 41 }, 42 { 43 k: Key{int8(1)}, 44 wantProto: listValueProto(stringProto("1")), 45 wantStr: "(1)", 46 }, 47 { 48 k: Key{int16(1)}, 49 wantProto: listValueProto(stringProto("1")), 50 wantStr: "(1)", 51 }, 52 { 53 k: Key{int32(1)}, 54 wantProto: listValueProto(stringProto("1")), 55 wantStr: "(1)", 56 }, 57 { 58 k: Key{int64(1)}, 59 wantProto: listValueProto(stringProto("1")), 60 wantStr: "(1)", 61 }, 62 { 63 k: Key{uint8(1)}, 64 wantProto: listValueProto(stringProto("1")), 65 wantStr: "(1)", 66 }, 67 { 68 k: Key{uint16(1)}, 69 wantProto: listValueProto(stringProto("1")), 70 wantStr: "(1)", 71 }, 72 { 73 k: Key{uint32(1)}, 74 wantProto: listValueProto(stringProto("1")), 75 wantStr: "(1)", 76 }, 77 { 78 k: Key{true}, 79 wantProto: listValueProto(boolProto(true)), 80 wantStr: "(true)", 81 }, 82 { 83 k: Key{float32(1.5)}, 84 wantProto: listValueProto(floatProto(1.5)), 85 wantStr: "(1.5)", 86 }, 87 { 88 k: Key{float64(1.5)}, 89 wantProto: listValueProto(floatProto(1.5)), 90 wantStr: "(1.5)", 91 }, 92 { 93 k: Key{"value"}, 94 wantProto: listValueProto(stringProto("value")), 95 wantStr: `("value")`, 96 }, 97 { 98 k: Key{[]byte(nil)}, 99 wantProto: listValueProto(nullProto()), 100 wantStr: "(<null>)", 101 }, 102 { 103 k: Key{[]byte{}}, 104 wantProto: listValueProto(stringProto("")), 105 wantStr: `("")`, 106 }, 107 { 108 k: Key{tm}, 109 wantProto: listValueProto(stringProto("2016-11-15T15:04:05.999999999Z")), 110 wantStr: `("2016-11-15T15:04:05.999999999Z")`, 111 }, 112 {k: Key{dt}, 113 wantProto: listValueProto(stringProto("2016-11-15")), 114 wantStr: `("2016-11-15")`, 115 }, 116 { 117 k: Key{[]byte("value")}, 118 wantProto: listValueProto(bytesProto([]byte("value"))), 119 wantStr: `("value")`, 120 }, 121 { 122 k: Key{NullInt64{1, true}}, 123 wantProto: listValueProto(stringProto("1")), 124 wantStr: "(1)", 125 }, 126 { 127 k: Key{NullInt64{2, false}}, 128 wantProto: listValueProto(nullProto()), 129 wantStr: "(<null>)", 130 }, 131 { 132 k: Key{NullFloat64{1.5, true}}, 133 wantProto: listValueProto(floatProto(1.5)), 134 wantStr: "(1.5)", 135 }, 136 { 137 k: Key{NullFloat64{2.0, false}}, 138 wantProto: listValueProto(nullProto()), 139 wantStr: "(<null>)", 140 }, 141 { 142 k: Key{NullBool{true, true}}, 143 wantProto: listValueProto(boolProto(true)), 144 wantStr: "(true)", 145 }, 146 { 147 k: Key{NullBool{true, false}}, 148 wantProto: listValueProto(nullProto()), 149 wantStr: "(<null>)", 150 }, 151 { 152 k: Key{NullString{"value", true}}, 153 wantProto: listValueProto(stringProto("value")), 154 wantStr: `("value")`, 155 }, 156 { 157 k: Key{NullString{"value", false}}, 158 wantProto: listValueProto(nullProto()), 159 wantStr: "(<null>)", 160 }, 161 { 162 k: Key{NullTime{tm, true}}, 163 wantProto: listValueProto(timeProto(tm)), 164 wantStr: `("2016-11-15T15:04:05.999999999Z")`, 165 }, 166 167 { 168 k: Key{NullTime{time.Now(), false}}, 169 wantProto: listValueProto(nullProto()), 170 wantStr: "(<null>)", 171 }, 172 { 173 k: Key{NullDate{dt, true}}, 174 wantProto: listValueProto(dateProto(dt)), 175 wantStr: `("2016-11-15")`, 176 }, 177 { 178 k: Key{NullDate{civil.Date{}, false}}, 179 wantProto: listValueProto(nullProto()), 180 wantStr: "(<null>)", 181 }, 182 { 183 k: Key{int(1), NullString{"value", false}, "value", 1.5, true}, 184 wantProto: listValueProto(stringProto("1"), nullProto(), stringProto("value"), floatProto(1.5), boolProto(true)), 185 wantStr: `(1,<null>,"value",1.5,true)`, 186 }, 187 } { 188 if got := test.k.String(); got != test.wantStr { 189 t.Errorf("%v.String() = %v, want %v", test.k, got, test.wantStr) 190 } 191 gotProto, err := test.k.proto() 192 if err != nil { 193 t.Errorf("%v.proto() returns error %v; want nil error", test.k, err) 194 } 195 if !testEqual(gotProto, test.wantProto) { 196 t.Errorf("%v.proto() = \n%v\nwant:\n%v", test.k, gotProto, test.wantProto) 197 } 198 } 199} 200 201// Test KeyRange.String() and KeyRange.proto(). 202func TestKeyRange(t *testing.T) { 203 for _, test := range []struct { 204 kr KeyRange 205 wantProto *sppb.KeyRange 206 wantStr string 207 }{ 208 { 209 kr: KeyRange{Key{"A"}, Key{"D"}, OpenOpen}, 210 wantProto: &sppb.KeyRange{ 211 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(stringProto("A"))}, 212 EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(stringProto("D"))}, 213 }, 214 wantStr: `(("A"),("D"))`, 215 }, 216 { 217 kr: KeyRange{Key{1}, Key{10}, OpenClosed}, 218 wantProto: &sppb.KeyRange{ 219 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(stringProto("1"))}, 220 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(stringProto("10"))}, 221 }, 222 wantStr: "((1),(10)]", 223 }, 224 { 225 kr: KeyRange{Key{1.5, 2.1, 0.2}, Key{1.9, 0.7}, ClosedOpen}, 226 wantProto: &sppb.KeyRange{ 227 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(floatProto(1.5), floatProto(2.1), floatProto(0.2))}, 228 EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(floatProto(1.9), floatProto(0.7))}, 229 }, 230 wantStr: "[(1.5,2.1,0.2),(1.9,0.7))", 231 }, 232 { 233 kr: KeyRange{Key{NullInt64{1, true}}, Key{10}, ClosedClosed}, 234 wantProto: &sppb.KeyRange{ 235 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(stringProto("1"))}, 236 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(stringProto("10"))}, 237 }, 238 wantStr: "[(1),(10)]", 239 }, 240 } { 241 if got := test.kr.String(); got != test.wantStr { 242 t.Errorf("%v.String() = %v, want %v", test.kr, got, test.wantStr) 243 } 244 gotProto, err := test.kr.proto() 245 if err != nil { 246 t.Errorf("%v.proto() returns error %v; want nil error", test.kr, err) 247 } 248 if !testEqual(gotProto, test.wantProto) { 249 t.Errorf("%v.proto() = \n%v\nwant:\n%v", test.kr, gotProto.String(), test.wantProto.String()) 250 } 251 } 252} 253 254func TestPrefixRange(t *testing.T) { 255 got := Key{1}.AsPrefix() 256 want := KeyRange{Start: Key{1}, End: Key{1}, Kind: ClosedClosed} 257 if !testEqual(got, want) { 258 t.Errorf("got %v, want %v", got, want) 259 } 260} 261 262func TestKeySets(t *testing.T) { 263 int1 := intProto(1) 264 int2 := intProto(2) 265 int3 := intProto(3) 266 int4 := intProto(4) 267 for i, test := range []struct { 268 ks KeySet 269 wantProto *sppb.KeySet 270 }{ 271 { 272 KeySets(), 273 &sppb.KeySet{}, 274 }, 275 { 276 Key{4}, 277 &sppb.KeySet{ 278 Keys: []*proto3.ListValue{listValueProto(int4)}, 279 }, 280 }, 281 { 282 AllKeys(), 283 &sppb.KeySet{All: true}, 284 }, 285 { 286 KeySets(Key{1, 2}, Key{3, 4}), 287 &sppb.KeySet{ 288 Keys: []*proto3.ListValue{ 289 listValueProto(int1, int2), 290 listValueProto(int3, int4), 291 }, 292 }, 293 }, 294 { 295 KeyRange{Key{1}, Key{2}, ClosedOpen}, 296 &sppb.KeySet{Ranges: []*sppb.KeyRange{ 297 { 298 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int1)}, 299 EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(int2)}, 300 }, 301 }}, 302 }, 303 { 304 Key{2}.AsPrefix(), 305 &sppb.KeySet{Ranges: []*sppb.KeyRange{ 306 { 307 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int2)}, 308 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int2)}, 309 }, 310 }}, 311 }, 312 { 313 KeySets( 314 KeyRange{Key{1}, Key{2}, ClosedClosed}, 315 KeyRange{Key{3}, Key{4}, OpenClosed}, 316 ), 317 &sppb.KeySet{ 318 Ranges: []*sppb.KeyRange{ 319 { 320 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int1)}, 321 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int2)}, 322 }, 323 { 324 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(int3)}, 325 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int4)}, 326 }, 327 }, 328 }, 329 }, 330 { 331 KeySets( 332 Key{1}, 333 KeyRange{Key{2}, Key{3}, ClosedClosed}, 334 KeyRange{Key{4}, Key{5}, OpenClosed}, 335 KeySets(), 336 Key{6}), 337 &sppb.KeySet{ 338 Keys: []*proto3.ListValue{ 339 listValueProto(int1), 340 listValueProto(intProto(6)), 341 }, 342 Ranges: []*sppb.KeyRange{ 343 { 344 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int2)}, 345 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int3)}, 346 }, 347 { 348 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(int4)}, 349 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(intProto(5))}, 350 }, 351 }, 352 }, 353 }, 354 { 355 KeySets( 356 Key{1}, 357 KeyRange{Key{2}, Key{3}, ClosedClosed}, 358 AllKeys(), 359 KeyRange{Key{4}, Key{5}, OpenClosed}, 360 Key{6}), 361 &sppb.KeySet{All: true}, 362 }, 363 } { 364 gotProto, err := test.ks.keySetProto() 365 if err != nil { 366 t.Errorf("#%d: %v.proto() returns error %v; want nil error", i, test.ks, err) 367 } 368 if !testEqual(gotProto, test.wantProto) { 369 t.Errorf("#%d: %v.proto() = \n%v\nwant:\n%v", i, test.ks, gotProto.String(), test.wantProto.String()) 370 } 371 } 372} 373