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 "errors" 21 "math/big" 22 "testing" 23 "time" 24 25 "cloud.google.com/go/civil" 26 proto3 "github.com/golang/protobuf/ptypes/struct" 27 sppb "google.golang.org/genproto/googleapis/spanner/v1" 28) 29 30type customKeyToString string 31 32func (k customKeyToString) EncodeSpanner() (interface{}, error) { 33 return string(k), nil 34} 35 36type customKeyToInt int 37 38func (k customKeyToInt) EncodeSpanner() (interface{}, error) { 39 return int(k), nil 40} 41 42type customKeyToError struct{} 43 44func (k customKeyToError) EncodeSpanner() (interface{}, error) { 45 return nil, errors.New("always error") 46} 47 48// Test Key.String() and Key.proto(). 49func TestKey(t *testing.T) { 50 tm, _ := time.Parse(time.RFC3339Nano, "2016-11-15T15:04:05.999999999Z") 51 dt, _ := civil.ParseDate("2016-11-15") 52 for _, test := range []struct { 53 k Key 54 wantProto *proto3.ListValue 55 wantStr string 56 }{ 57 { 58 k: Key{int(1)}, 59 wantProto: listValueProto(stringProto("1")), 60 wantStr: "(1)", 61 }, 62 { 63 k: Key{int8(1)}, 64 wantProto: listValueProto(stringProto("1")), 65 wantStr: "(1)", 66 }, 67 { 68 k: Key{int16(1)}, 69 wantProto: listValueProto(stringProto("1")), 70 wantStr: "(1)", 71 }, 72 { 73 k: Key{int32(1)}, 74 wantProto: listValueProto(stringProto("1")), 75 wantStr: "(1)", 76 }, 77 { 78 k: Key{int64(1)}, 79 wantProto: listValueProto(stringProto("1")), 80 wantStr: "(1)", 81 }, 82 { 83 k: Key{uint8(1)}, 84 wantProto: listValueProto(stringProto("1")), 85 wantStr: "(1)", 86 }, 87 { 88 k: Key{uint16(1)}, 89 wantProto: listValueProto(stringProto("1")), 90 wantStr: "(1)", 91 }, 92 { 93 k: Key{uint32(1)}, 94 wantProto: listValueProto(stringProto("1")), 95 wantStr: "(1)", 96 }, 97 { 98 k: Key{true}, 99 wantProto: listValueProto(boolProto(true)), 100 wantStr: "(true)", 101 }, 102 { 103 k: Key{float32(1.5)}, 104 wantProto: listValueProto(floatProto(1.5)), 105 wantStr: "(1.5)", 106 }, 107 { 108 k: Key{float64(1.5)}, 109 wantProto: listValueProto(floatProto(1.5)), 110 wantStr: "(1.5)", 111 }, 112 { 113 k: Key{"value"}, 114 wantProto: listValueProto(stringProto("value")), 115 wantStr: `("value")`, 116 }, 117 { 118 k: Key{[]byte(nil)}, 119 wantProto: listValueProto(nullProto()), 120 wantStr: "(<null>)", 121 }, 122 { 123 k: Key{[]byte{}}, 124 wantProto: listValueProto(stringProto("")), 125 wantStr: `("")`, 126 }, 127 { 128 k: Key{tm}, 129 wantProto: listValueProto(stringProto("2016-11-15T15:04:05.999999999Z")), 130 wantStr: `("2016-11-15T15:04:05.999999999Z")`, 131 }, 132 {k: Key{dt}, 133 wantProto: listValueProto(stringProto("2016-11-15")), 134 wantStr: `("2016-11-15")`, 135 }, 136 { 137 k: Key{*big.NewRat(1, 1)}, 138 wantProto: listValueProto(stringProto("1.000000000")), 139 wantStr: `(1.000000000)`, 140 }, 141 { 142 k: Key{[]byte("value")}, 143 wantProto: listValueProto(bytesProto([]byte("value"))), 144 wantStr: `("value")`, 145 }, 146 { 147 k: Key{NullInt64{1, true}}, 148 wantProto: listValueProto(stringProto("1")), 149 wantStr: "(1)", 150 }, 151 { 152 k: Key{NullInt64{2, false}}, 153 wantProto: listValueProto(nullProto()), 154 wantStr: "(<null>)", 155 }, 156 { 157 k: Key{NullFloat64{1.5, true}}, 158 wantProto: listValueProto(floatProto(1.5)), 159 wantStr: "(1.5)", 160 }, 161 { 162 k: Key{NullFloat64{2.0, false}}, 163 wantProto: listValueProto(nullProto()), 164 wantStr: "(<null>)", 165 }, 166 { 167 k: Key{NullBool{true, true}}, 168 wantProto: listValueProto(boolProto(true)), 169 wantStr: "(true)", 170 }, 171 { 172 k: Key{NullBool{true, false}}, 173 wantProto: listValueProto(nullProto()), 174 wantStr: "(<null>)", 175 }, 176 { 177 k: Key{NullString{"value", true}}, 178 wantProto: listValueProto(stringProto("value")), 179 wantStr: `("value")`, 180 }, 181 { 182 k: Key{NullString{"value", false}}, 183 wantProto: listValueProto(nullProto()), 184 wantStr: "(<null>)", 185 }, 186 { 187 k: Key{NullTime{tm, true}}, 188 wantProto: listValueProto(timeProto(tm)), 189 wantStr: `("2016-11-15T15:04:05.999999999Z")`, 190 }, 191 192 { 193 k: Key{NullTime{time.Now(), false}}, 194 wantProto: listValueProto(nullProto()), 195 wantStr: "(<null>)", 196 }, 197 { 198 k: Key{NullDate{dt, true}}, 199 wantProto: listValueProto(dateProto(dt)), 200 wantStr: `("2016-11-15")`, 201 }, 202 { 203 k: Key{NullDate{civil.Date{}, false}}, 204 wantProto: listValueProto(nullProto()), 205 wantStr: "(<null>)", 206 }, 207 { 208 k: Key{int(1), NullString{"value", false}, "value", 1.5, true}, 209 wantProto: listValueProto(stringProto("1"), nullProto(), stringProto("value"), floatProto(1.5), boolProto(true)), 210 wantStr: `(1,<null>,"value",1.5,true)`, 211 }, 212 { 213 k: Key{NullNumeric{*big.NewRat(2, 3), true}}, 214 wantProto: listValueProto(stringProto("0.666666667")), 215 wantStr: "(0.666666667)", 216 }, 217 { 218 k: Key{NullNumeric{big.Rat{}, false}}, 219 wantProto: listValueProto(nullProto()), 220 wantStr: "(<null>)", 221 }, 222 { 223 k: Key{customKeyToString("value")}, 224 wantProto: listValueProto(stringProto("value")), 225 wantStr: `("value")`, 226 }, 227 { 228 k: Key{customKeyToInt(1)}, 229 wantProto: listValueProto(intProto(1)), 230 wantStr: `(1)`, 231 }, 232 { 233 k: Key{customKeyToError{}}, 234 wantProto: nil, 235 wantStr: `(error)`, 236 }, 237 } { 238 if got := test.k.String(); got != test.wantStr { 239 t.Errorf("%v.String() = %v, want %v", test.k, got, test.wantStr) 240 } 241 gotProto, err := test.k.proto() 242 if test.wantProto != nil && err != nil { 243 t.Errorf("%v.proto() returns error %v; want nil error", test.k, err) 244 } 245 if !testEqual(gotProto, test.wantProto) { 246 t.Errorf("%v.proto() = \n%v\nwant:\n%v", test.k, gotProto, test.wantProto) 247 } 248 } 249} 250 251// Test KeyRange.String() and KeyRange.proto(). 252func TestKeyRange(t *testing.T) { 253 for _, test := range []struct { 254 kr KeyRange 255 wantProto *sppb.KeyRange 256 wantStr string 257 }{ 258 { 259 kr: KeyRange{Key{"A"}, Key{"D"}, OpenOpen}, 260 wantProto: &sppb.KeyRange{ 261 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(stringProto("A"))}, 262 EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(stringProto("D"))}, 263 }, 264 wantStr: `(("A"),("D"))`, 265 }, 266 { 267 kr: KeyRange{Key{1}, Key{10}, OpenClosed}, 268 wantProto: &sppb.KeyRange{ 269 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(stringProto("1"))}, 270 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(stringProto("10"))}, 271 }, 272 wantStr: "((1),(10)]", 273 }, 274 { 275 kr: KeyRange{Key{1.5, 2.1, 0.2}, Key{1.9, 0.7}, ClosedOpen}, 276 wantProto: &sppb.KeyRange{ 277 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(floatProto(1.5), floatProto(2.1), floatProto(0.2))}, 278 EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(floatProto(1.9), floatProto(0.7))}, 279 }, 280 wantStr: "[(1.5,2.1,0.2),(1.9,0.7))", 281 }, 282 { 283 kr: KeyRange{Key{NullInt64{1, true}}, Key{10}, ClosedClosed}, 284 wantProto: &sppb.KeyRange{ 285 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(stringProto("1"))}, 286 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(stringProto("10"))}, 287 }, 288 wantStr: "[(1),(10)]", 289 }, 290 { 291 kr: KeyRange{Key{customKeyToString("A")}, Key{customKeyToString("D")}, OpenOpen}, 292 wantProto: &sppb.KeyRange{ 293 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(stringProto("A"))}, 294 EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(stringProto("D"))}, 295 }, 296 wantStr: `(("A"),("D"))`, 297 }, 298 } { 299 if got := test.kr.String(); got != test.wantStr { 300 t.Errorf("%v.String() = %v, want %v", test.kr, got, test.wantStr) 301 } 302 gotProto, err := test.kr.proto() 303 if err != nil { 304 t.Errorf("%v.proto() returns error %v; want nil error", test.kr, err) 305 } 306 if !testEqual(gotProto, test.wantProto) { 307 t.Errorf("%v.proto() = \n%v\nwant:\n%v", test.kr, gotProto.String(), test.wantProto.String()) 308 } 309 } 310} 311 312func TestPrefixRange(t *testing.T) { 313 got := Key{1}.AsPrefix() 314 want := KeyRange{Start: Key{1}, End: Key{1}, Kind: ClosedClosed} 315 if !testEqual(got, want) { 316 t.Errorf("got %v, want %v", got, want) 317 } 318} 319 320func TestKeySetFromKeys(t *testing.T) { 321 for i, test := range []struct { 322 ks KeySet 323 wantProto *sppb.KeySet 324 }{ 325 { 326 KeySetFromKeys(), 327 &sppb.KeySet{}, 328 }, 329 { 330 KeySetFromKeys(Key{1}), 331 &sppb.KeySet{ 332 Keys: []*proto3.ListValue{ 333 listValueProto(intProto(1)), 334 }, 335 }, 336 }, 337 { 338 KeySetFromKeys(Key{1}, Key{2}), 339 &sppb.KeySet{ 340 Keys: []*proto3.ListValue{ 341 listValueProto(intProto(1)), 342 listValueProto(intProto(2)), 343 }, 344 }, 345 }, 346 { 347 KeySetFromKeys(Key{1, "one"}, Key{2, "two"}), 348 &sppb.KeySet{ 349 Keys: []*proto3.ListValue{ 350 listValueProto(intProto(1), stringProto("one")), 351 listValueProto(intProto(2), stringProto("two")), 352 }, 353 }, 354 }, 355 } { 356 gotProto, err := test.ks.keySetProto() 357 if err != nil { 358 t.Errorf("#%d: %v.proto() returns error %v; want nil error", i, test.ks, err) 359 } 360 if !testEqual(gotProto, test.wantProto) { 361 t.Errorf("#%d: %v.proto() = \n%v\nwant:\n%v", i, test.ks, gotProto.String(), test.wantProto.String()) 362 } 363 } 364} 365 366func TestKeySets(t *testing.T) { 367 int1 := intProto(1) 368 int2 := intProto(2) 369 int3 := intProto(3) 370 int4 := intProto(4) 371 for i, test := range []struct { 372 ks KeySet 373 wantProto *sppb.KeySet 374 }{ 375 { 376 KeySets(), 377 &sppb.KeySet{}, 378 }, 379 { 380 Key{4}, 381 &sppb.KeySet{ 382 Keys: []*proto3.ListValue{listValueProto(int4)}, 383 }, 384 }, 385 { 386 AllKeys(), 387 &sppb.KeySet{All: true}, 388 }, 389 { 390 KeySets(Key{1, 2}, Key{3, 4}), 391 &sppb.KeySet{ 392 Keys: []*proto3.ListValue{ 393 listValueProto(int1, int2), 394 listValueProto(int3, int4), 395 }, 396 }, 397 }, 398 { 399 KeyRange{Key{1}, Key{2}, ClosedOpen}, 400 &sppb.KeySet{Ranges: []*sppb.KeyRange{ 401 { 402 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int1)}, 403 EndKeyType: &sppb.KeyRange_EndOpen{EndOpen: listValueProto(int2)}, 404 }, 405 }}, 406 }, 407 { 408 Key{2}.AsPrefix(), 409 &sppb.KeySet{Ranges: []*sppb.KeyRange{ 410 { 411 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int2)}, 412 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int2)}, 413 }, 414 }}, 415 }, 416 { 417 KeySets( 418 KeyRange{Key{1}, Key{2}, ClosedClosed}, 419 KeyRange{Key{3}, Key{4}, OpenClosed}, 420 ), 421 &sppb.KeySet{ 422 Ranges: []*sppb.KeyRange{ 423 { 424 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int1)}, 425 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int2)}, 426 }, 427 { 428 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(int3)}, 429 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int4)}, 430 }, 431 }, 432 }, 433 }, 434 { 435 KeySets( 436 Key{1}, 437 KeyRange{Key{2}, Key{3}, ClosedClosed}, 438 KeyRange{Key{4}, Key{5}, OpenClosed}, 439 KeySets(), 440 Key{6}), 441 &sppb.KeySet{ 442 Keys: []*proto3.ListValue{ 443 listValueProto(int1), 444 listValueProto(intProto(6)), 445 }, 446 Ranges: []*sppb.KeyRange{ 447 { 448 StartKeyType: &sppb.KeyRange_StartClosed{StartClosed: listValueProto(int2)}, 449 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(int3)}, 450 }, 451 { 452 StartKeyType: &sppb.KeyRange_StartOpen{StartOpen: listValueProto(int4)}, 453 EndKeyType: &sppb.KeyRange_EndClosed{EndClosed: listValueProto(intProto(5))}, 454 }, 455 }, 456 }, 457 }, 458 { 459 KeySets( 460 Key{1}, 461 KeyRange{Key{2}, Key{3}, ClosedClosed}, 462 AllKeys(), 463 KeyRange{Key{4}, Key{5}, OpenClosed}, 464 Key{6}), 465 &sppb.KeySet{All: true}, 466 }, 467 { 468 KeySets( 469 Key{customKeyToInt(1), customKeyToInt(2)}, 470 Key{customKeyToInt(3), customKeyToInt(4)}, 471 ), 472 &sppb.KeySet{ 473 Keys: []*proto3.ListValue{ 474 listValueProto(int1, int2), 475 listValueProto(int3, int4), 476 }, 477 }, 478 }, 479 } { 480 gotProto, err := test.ks.keySetProto() 481 if err != nil { 482 t.Errorf("#%d: %v.proto() returns error %v; want nil error", i, test.ks, err) 483 } 484 if !testEqual(gotProto, test.wantProto) { 485 t.Errorf("#%d: %v.proto() = \n%v\nwant:\n%v", i, test.ks, gotProto.String(), test.wantProto.String()) 486 } 487 } 488} 489