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	"encoding/json"
21	"fmt"
22	"math"
23	"reflect"
24	"testing"
25	"time"
26
27	"cloud.google.com/go/civil"
28	"cloud.google.com/go/internal/testutil"
29	"github.com/golang/protobuf/proto"
30	proto3 "github.com/golang/protobuf/ptypes/struct"
31	"github.com/google/go-cmp/cmp"
32	sppb "google.golang.org/genproto/googleapis/spanner/v1"
33)
34
35var (
36	t1 = mustParseTime("2016-11-15T15:04:05.999999999Z")
37	// Boundaries
38	t2 = mustParseTime("0001-01-01T00:00:00.000000000Z")
39	t3 = mustParseTime("9999-12-31T23:59:59.999999999Z")
40	// Local timezone
41	t4 = time.Now()
42	d1 = mustParseDate("2016-11-15")
43	d2 = mustParseDate("1678-01-01")
44)
45
46func mustParseTime(s string) time.Time {
47	t, err := time.Parse(time.RFC3339Nano, s)
48	if err != nil {
49		panic(err)
50	}
51	return t
52}
53
54func mustParseDate(s string) civil.Date {
55	d, err := civil.ParseDate(s)
56	if err != nil {
57		panic(err)
58	}
59	return d
60}
61
62// Test encoding Values.
63func TestEncodeValue(t *testing.T) {
64	type CustomString string
65	type CustomBytes []byte
66	type CustomInt64 int64
67	type CustomBool bool
68	type CustomFloat64 float64
69	type CustomTime time.Time
70	type CustomDate civil.Date
71
72	type CustomNullString NullString
73	type CustomNullInt64 NullInt64
74	type CustomNullBool NullBool
75	type CustomNullFloat64 NullFloat64
76	type CustomNullTime NullTime
77	type CustomNullDate NullDate
78
79	sValue := "abc"
80	var sNilPtr *string
81	iValue := int64(7)
82	var iNilPtr *int64
83	bValue := true
84	var bNilPtr *bool
85	fValue := 3.14
86	var fNilPtr *float64
87	tValue := t1
88	var tNilPtr *time.Time
89	dValue := d1
90	var dNilPtr *civil.Date
91
92	var (
93		tString = stringType()
94		tInt    = intType()
95		tBool   = boolType()
96		tFloat  = floatType()
97		tBytes  = bytesType()
98		tTime   = timeType()
99		tDate   = dateType()
100	)
101	for i, test := range []struct {
102		in       interface{}
103		want     *proto3.Value
104		wantType *sppb.Type
105		name     string
106	}{
107		// STRING / STRING ARRAY:
108		{"abc", stringProto("abc"), tString, "string"},
109		{NullString{"abc", true}, stringProto("abc"), tString, "NullString with value"},
110		{NullString{"abc", false}, nullProto(), tString, "NullString with null"},
111		{&sValue, stringProto("abc"), tString, "*string with value"},
112		{sNilPtr, nullProto(), tString, "*string with null"},
113		{[]string(nil), nullProto(), listType(tString), "null []string"},
114		{[]string{"abc", "bcd"}, listProto(stringProto("abc"), stringProto("bcd")), listType(tString), "[]string"},
115		{[]NullString{{"abcd", true}, {"xyz", false}}, listProto(stringProto("abcd"), nullProto()), listType(tString), "[]NullString"},
116		{[]*string{&sValue, sNilPtr}, listProto(stringProto("abc"), nullProto()), listType(tString), "[]*string"},
117		// BYTES / BYTES ARRAY
118		{[]byte("foo"), bytesProto([]byte("foo")), tBytes, "[]byte with value"},
119		{[]byte(nil), nullProto(), tBytes, "null []byte"},
120		{[][]byte{nil, []byte("ab")}, listProto(nullProto(), bytesProto([]byte("ab"))), listType(tBytes), "[][]byte"},
121		{[][]byte(nil), nullProto(), listType(tBytes), "null [][]byte"},
122		// INT64 / INT64 ARRAY
123		{7, intProto(7), tInt, "int"},
124		{[]int(nil), nullProto(), listType(tInt), "null []int"},
125		{[]int{31, 127}, listProto(intProto(31), intProto(127)), listType(tInt), "[]int"},
126		{int64(81), intProto(81), tInt, "int64"},
127		{[]int64(nil), nullProto(), listType(tInt), "null []int64"},
128		{[]int64{33, 129}, listProto(intProto(33), intProto(129)), listType(tInt), "[]int64"},
129		{NullInt64{11, true}, intProto(11), tInt, "NullInt64 with value"},
130		{NullInt64{11, false}, nullProto(), tInt, "NullInt64 with null"},
131		{&iValue, intProto(7), tInt, "*int64 with value"},
132		{iNilPtr, nullProto(), tInt, "*int64 with null"},
133		{[]NullInt64{{35, true}, {131, false}}, listProto(intProto(35), nullProto()), listType(tInt), "[]NullInt64"},
134		{[]*int64{&iValue, iNilPtr}, listProto(intProto(7), nullProto()), listType(tInt), "[]*int64"},
135		// BOOL / BOOL ARRAY
136		{true, boolProto(true), tBool, "bool"},
137		{NullBool{true, true}, boolProto(true), tBool, "NullBool with value"},
138		{NullBool{true, false}, nullProto(), tBool, "NullBool with null"},
139		{&bValue, boolProto(true), tBool, "*bool with value"},
140		{bNilPtr, nullProto(), tBool, "*bool with null"},
141		{[]bool{true, false}, listProto(boolProto(true), boolProto(false)), listType(tBool), "[]bool"},
142		{[]NullBool{{true, true}, {true, false}}, listProto(boolProto(true), nullProto()), listType(tBool), "[]NullBool"},
143		{[]*bool{&bValue, bNilPtr}, listProto(boolProto(true), nullProto()), listType(tBool), "[]*bool"},
144		// FLOAT64 / FLOAT64 ARRAY
145		{3.14, floatProto(3.14), tFloat, "float"},
146		{NullFloat64{3.1415, true}, floatProto(3.1415), tFloat, "NullFloat64 with value"},
147		{NullFloat64{math.Inf(1), true}, floatProto(math.Inf(1)), tFloat, "NullFloat64 with infinity"},
148		{NullFloat64{3.14159, false}, nullProto(), tFloat, "NullFloat64 with null"},
149		{&fValue, floatProto(3.14), tFloat, "*float64 with value"},
150		{fNilPtr, nullProto(), tFloat, "*float64 with null"},
151		{[]float64(nil), nullProto(), listType(tFloat), "null []float64"},
152		{[]float64{3.141, 0.618, math.Inf(-1)}, listProto(floatProto(3.141), floatProto(0.618), floatProto(math.Inf(-1))), listType(tFloat), "[]float64"},
153		{[]NullFloat64{{3.141, true}, {0.618, false}}, listProto(floatProto(3.141), nullProto()), listType(tFloat), "[]NullFloat64"},
154		{[]*float64{&fValue, fNilPtr}, listProto(floatProto(3.14), nullProto()), listType(tFloat), "[]NullFloat64"},
155		// TIMESTAMP / TIMESTAMP ARRAY
156		{t1, timeProto(t1), tTime, "time"},
157		{NullTime{t1, true}, timeProto(t1), tTime, "NullTime with value"},
158		{NullTime{t1, false}, nullProto(), tTime, "NullTime with null"},
159		{&tValue, timeProto(t1), tTime, "*time.Time with value"},
160		{tNilPtr, nullProto(), tTime, "*time.Time with null"},
161		{[]time.Time(nil), nullProto(), listType(tTime), "null []time"},
162		{[]time.Time{t1, t2, t3, t4}, listProto(timeProto(t1), timeProto(t2), timeProto(t3), timeProto(t4)), listType(tTime), "[]time"},
163		{[]NullTime{{t1, true}, {t1, false}}, listProto(timeProto(t1), nullProto()), listType(tTime), "[]NullTime"},
164		{[]*time.Time{&tValue, tNilPtr}, listProto(timeProto(t1), nullProto()), listType(tTime), "[]*time.Time"},
165		// DATE / DATE ARRAY
166		{d1, dateProto(d1), tDate, "date"},
167		{NullDate{d1, true}, dateProto(d1), tDate, "NullDate with value"},
168		{NullDate{civil.Date{}, false}, nullProto(), tDate, "NullDate with null"},
169		{&dValue, dateProto(d1), tDate, "*civil.Date with value"},
170		{dNilPtr, nullProto(), tDate, "*civil.Date with null"},
171		{[]civil.Date(nil), nullProto(), listType(tDate), "null []date"},
172		{[]civil.Date{d1, d2}, listProto(dateProto(d1), dateProto(d2)), listType(tDate), "[]date"},
173		{[]NullDate{{d1, true}, {civil.Date{}, false}}, listProto(dateProto(d1), nullProto()), listType(tDate), "[]NullDate"},
174		{[]*civil.Date{&dValue, dNilPtr}, listProto(dateProto(d1), nullProto()), listType(tDate), "[]*civil.Date"},
175		// GenericColumnValue
176		{GenericColumnValue{tString, stringProto("abc")}, stringProto("abc"), tString, "GenericColumnValue with value"},
177		{GenericColumnValue{tString, nullProto()}, nullProto(), tString, "GenericColumnValue with null"},
178		// not actually valid (stringProto inside int list), but demonstrates pass-through.
179		{
180			GenericColumnValue{
181				Type:  listType(tInt),
182				Value: listProto(intProto(5), nullProto(), stringProto("bcd")),
183			},
184			listProto(intProto(5), nullProto(), stringProto("bcd")),
185			listType(tInt),
186			"pass-through",
187		},
188		// placeholder
189		{CommitTimestamp, stringProto(commitTimestampPlaceholderString), tTime, "CommitTimestampPlaceholder"},
190		// CUSTOM STRING / CUSTOM STRING ARRAY
191		{CustomString("abc"), stringProto("abc"), tString, "CustomString"},
192		{CustomNullString{"abc", true}, stringProto("abc"), tString, "CustomNullString with value"},
193		{CustomNullString{"abc", false}, nullProto(), tString, "CustomNullString with null"},
194		{[]CustomString(nil), nullProto(), listType(tString), "null []CustomString"},
195		{[]CustomString{"abc", "bcd"}, listProto(stringProto("abc"), stringProto("bcd")), listType(tString), "[]CustomString"},
196		{[]CustomNullString(nil), nullProto(), listType(tString), "null []NullCustomString"},
197		{[]CustomNullString{{"abcd", true}, {"xyz", false}}, listProto(stringProto("abcd"), nullProto()), listType(tString), "[]NullCustomString"},
198		// CUSTOM BYTES / CUSTOM BYTES ARRAY
199		{CustomBytes("foo"), bytesProto([]byte("foo")), tBytes, "CustomBytes with value"},
200		{CustomBytes(nil), nullProto(), tBytes, "null CustomBytes"},
201		{[]CustomBytes{nil, CustomBytes("ab")}, listProto(nullProto(), bytesProto([]byte("ab"))), listType(tBytes), "[]CustomBytes"},
202		{[]CustomBytes(nil), nullProto(), listType(tBytes), "null []CustomBytes"},
203		// CUSTOM INT64 / CUSTOM INT64 ARRAY
204		{CustomInt64(81), intProto(81), tInt, "CustomInt64"},
205		{[]CustomInt64(nil), nullProto(), listType(tInt), "null []CustomInt64"},
206		{[]CustomInt64{33, 129}, listProto(intProto(33), intProto(129)), listType(tInt), "[]CustomInt64"},
207		{CustomNullInt64{11, true}, intProto(11), tInt, "CustomNullInt64 with value"},
208		{CustomNullInt64{11, false}, nullProto(), tInt, "CustomNullInt64 with null"},
209		{[]CustomNullInt64(nil), nullProto(), listType(tInt), "null []CustomNullInt64"},
210		{[]CustomNullInt64{{35, true}, {131, false}}, listProto(intProto(35), nullProto()), listType(tInt), "[]CustomNullInt64"},
211		// CUSTOM BOOL / CUSTOM BOOL ARRAY
212		{CustomBool(true), boolProto(true), tBool, "CustomBool"},
213		{CustomNullBool{true, true}, boolProto(true), tBool, "CustomNullBool with value"},
214		{CustomNullBool{true, false}, nullProto(), tBool, "CustomNullBool with null"},
215		{[]CustomBool{true, false}, listProto(boolProto(true), boolProto(false)), listType(tBool), "[]CustomBool"},
216		{[]CustomNullBool{{true, true}, {true, false}}, listProto(boolProto(true), nullProto()), listType(tBool), "[]CustomNullBool"},
217		// FLOAT64 / FLOAT64 ARRAY
218		{CustomFloat64(3.14), floatProto(3.14), tFloat, "CustomFloat64"},
219		{CustomNullFloat64{3.1415, true}, floatProto(3.1415), tFloat, "CustomNullFloat64 with value"},
220		{CustomNullFloat64{math.Inf(1), true}, floatProto(math.Inf(1)), tFloat, "CustomNullFloat64 with infinity"},
221		{CustomNullFloat64{3.14159, false}, nullProto(), tFloat, "CustomNullFloat64 with null"},
222		{[]CustomFloat64(nil), nullProto(), listType(tFloat), "null []CustomFloat64"},
223		{[]CustomFloat64{3.141, 0.618, CustomFloat64(math.Inf(-1))}, listProto(floatProto(3.141), floatProto(0.618), floatProto(math.Inf(-1))), listType(tFloat), "[]CustomFloat64"},
224		{[]CustomNullFloat64(nil), nullProto(), listType(tFloat), "null []CustomNullFloat64"},
225		{[]CustomNullFloat64{{3.141, true}, {0.618, false}}, listProto(floatProto(3.141), nullProto()), listType(tFloat), "[]CustomNullFloat64"},
226		// CUSTOM TIMESTAMP / CUSTOM TIMESTAMP ARRAY
227		{CustomTime(t1), timeProto(t1), tTime, "CustomTime"},
228		{CustomNullTime{t1, true}, timeProto(t1), tTime, "CustomNullTime with value"},
229		{CustomNullTime{t1, false}, nullProto(), tTime, "CustomNullTime with null"},
230		{[]CustomTime(nil), nullProto(), listType(tTime), "null []CustomTime"},
231		{[]CustomTime{CustomTime(t1), CustomTime(t2), CustomTime(t3), CustomTime(t4)}, listProto(timeProto(t1), timeProto(t2), timeProto(t3), timeProto(t4)), listType(tTime), "[]CustomTime"},
232		{[]CustomNullTime(nil), nullProto(), listType(tTime), "null []CustomNullTime"},
233		{[]CustomNullTime{{t1, true}, {t1, false}}, listProto(timeProto(t1), nullProto()), listType(tTime), "[]CustomNullTime"},
234		// CUSTOM DATE / CUSTOM DATE ARRAY
235		{CustomDate(d1), dateProto(d1), tDate, "CustomDate"},
236		{CustomNullDate{d1, true}, dateProto(d1), tDate, "CustomNullDate with value"},
237		{CustomNullDate{civil.Date{}, false}, nullProto(), tDate, "CustomNullDate with null"},
238		{[]CustomDate(nil), nullProto(), listType(tDate), "null []CustomDate"},
239		{[]CustomDate{CustomDate(d1), CustomDate(d2)}, listProto(dateProto(d1), dateProto(d2)), listType(tDate), "[]CustomDate"},
240		{[]CustomNullDate(nil), nullProto(), listType(tDate), "null []CustomNullDate"},
241		{[]CustomNullDate{{d1, true}, {civil.Date{}, false}}, listProto(dateProto(d1), nullProto()), listType(tDate), "[]NullDate"},
242	} {
243		got, gotType, err := encodeValue(test.in)
244		if err != nil {
245			t.Fatalf("#%d (%s): got error during encoding: %v, want nil", i, test.name, err)
246		}
247		if !testEqual(got, test.want) {
248			t.Errorf("#%d (%s): got encode result: %v, want %v", i, test.name, got, test.want)
249		}
250		if !testEqual(gotType, test.wantType) {
251			t.Errorf("#%d (%s): got encode type: %v, want %v", i, test.name, gotType, test.wantType)
252		}
253	}
254}
255
256type encodeTest struct {
257	desc     string
258	in       interface{}
259	want     *proto3.Value
260	wantType *sppb.Type
261}
262
263func checkStructEncoding(desc string, got *proto3.Value, gotType *sppb.Type,
264	want *proto3.Value, wantType *sppb.Type, t *testing.T) {
265	if !testEqual(got, want) {
266		t.Errorf("Test %s: got encode result: %v, want %v", desc, got, want)
267	}
268	if !testEqual(gotType, wantType) {
269		t.Errorf("Test %s: got encode type: %v, want %v", desc, gotType, wantType)
270	}
271}
272
273// Testcase code
274func encodeStructValue(test encodeTest, t *testing.T) {
275	got, gotType, err := encodeValue(test.in)
276	if err != nil {
277		t.Fatalf("Test %s: got error during encoding: %v, want nil", test.desc, err)
278	}
279	checkStructEncoding(test.desc, got, gotType, test.want, test.wantType, t)
280}
281
282func TestEncodeStructValuePointers(t *testing.T) {
283	type structf struct {
284		F int `spanner:"ff2"`
285	}
286	nestedStructProto := structType(mkField("ff2", intType()))
287
288	type testType struct {
289		Stringf    string
290		Structf    *structf
291		ArrStructf []*structf
292	}
293	testTypeProto := structType(
294		mkField("Stringf", stringType()),
295		mkField("Structf", nestedStructProto),
296		mkField("ArrStructf", listType(nestedStructProto)))
297
298	for _, test := range []encodeTest{
299		{
300			"Pointer to Go struct with pointers-to-(array)-struct fields.",
301			&testType{"hello", &structf{50}, []*structf{{30}, {40}}},
302			listProto(
303				stringProto("hello"),
304				listProto(intProto(50)),
305				listProto(
306					listProto(intProto(30)),
307					listProto(intProto(40)))),
308			testTypeProto,
309		},
310		{
311			"Nil pointer to Go struct representing a NULL struct value.",
312			(*testType)(nil),
313			nullProto(),
314			testTypeProto,
315		},
316		{
317			"Slice of pointers to Go structs with NULL and non-NULL elements.",
318			[]*testType{
319				(*testType)(nil),
320				{"hello", nil, []*structf{nil, {40}}},
321				{"world", &structf{70}, nil},
322			},
323			listProto(
324				nullProto(),
325				listProto(
326					stringProto("hello"),
327					nullProto(),
328					listProto(nullProto(), listProto(intProto(40)))),
329				listProto(
330					stringProto("world"),
331					listProto(intProto(70)),
332					nullProto())),
333			listType(testTypeProto),
334		},
335		{
336			"Nil slice of pointers to structs representing a NULL array of structs.",
337			[]*testType(nil),
338			nullProto(),
339			listType(testTypeProto),
340		},
341		{
342			"Empty slice of pointers to structs representing an empty array of structs.",
343			[]*testType{},
344			listProto(),
345			listType(testTypeProto),
346		},
347	} {
348		encodeStructValue(test, t)
349	}
350}
351
352func TestEncodeStructValueErrors(t *testing.T) {
353	type Embedded struct {
354		A int
355	}
356	type embedded struct {
357		B bool
358	}
359	x := 0
360
361	for _, test := range []struct {
362		desc    string
363		in      interface{}
364		wantErr error
365	}{
366		{
367			"Unsupported embedded fields.",
368			struct{ Embedded }{Embedded{10}},
369			errUnsupportedEmbeddedStructFields("Embedded"),
370		},
371		{
372			"Unsupported pointer to embedded fields.",
373			struct{ *Embedded }{&Embedded{10}},
374			errUnsupportedEmbeddedStructFields("Embedded"),
375		},
376		{
377			"Unsupported embedded + unexported fields.",
378			struct {
379				int
380				*bool
381				embedded
382			}{10, nil, embedded{false}},
383			errUnsupportedEmbeddedStructFields("int"),
384		},
385		{
386			"Unsupported type.",
387			(**struct{})(nil),
388			errEncoderUnsupportedType((**struct{})(nil)),
389		},
390		{
391			"Unsupported type.",
392			3,
393			errEncoderUnsupportedType(3),
394		},
395		{
396			"Unsupported type.",
397			&x,
398			errEncoderUnsupportedType(&x),
399		},
400	} {
401		_, _, got := encodeStruct(test.in)
402		if got == nil || !testEqual(test.wantErr, got) {
403			t.Errorf("Test: %s, expected error %v during decoding, got %v", test.desc, test.wantErr, got)
404		}
405	}
406}
407
408func TestEncodeStructValueArrayStructFields(t *testing.T) {
409	type structf struct {
410		Intff int
411	}
412
413	structfType := structType(mkField("Intff", intType()))
414	for _, test := range []encodeTest{
415		{
416			"Unnamed array-of-struct-typed field.",
417			struct {
418				Intf       int
419				ArrStructf []structf `spanner:""`
420			}{10, []structf{{1}, {2}}},
421			listProto(
422				intProto(10),
423				listProto(
424					listProto(intProto(1)),
425					listProto(intProto(2)))),
426			structType(
427				mkField("Intf", intType()),
428				mkField("", listType(structfType))),
429		},
430		{
431			"Null array-of-struct-typed field.",
432			struct {
433				Intf       int
434				ArrStructf []structf
435			}{10, []structf(nil)},
436			listProto(intProto(10), nullProto()),
437			structType(
438				mkField("Intf", intType()),
439				mkField("ArrStructf", listType(structfType))),
440		},
441		{
442			"Array-of-struct-typed field representing empty array.",
443			struct {
444				Intf       int
445				ArrStructf []structf
446			}{10, []structf{}},
447			listProto(intProto(10), listProto([]*proto3.Value{}...)),
448			structType(
449				mkField("Intf", intType()),
450				mkField("ArrStructf", listType(structfType))),
451		},
452		{
453			"Array-of-struct-typed field with nullable struct elements.",
454			struct {
455				Intf       int
456				ArrStructf []*structf
457			}{
458				10,
459				[]*structf{(*structf)(nil), {1}},
460			},
461			listProto(
462				intProto(10),
463				listProto(
464					nullProto(),
465					listProto(intProto(1)))),
466			structType(
467				mkField("Intf", intType()),
468				mkField("ArrStructf", listType(structfType))),
469		},
470	} {
471		encodeStructValue(test, t)
472	}
473}
474
475func TestEncodeStructValueStructFields(t *testing.T) {
476	type structf struct {
477		Intff int
478	}
479	structfType := structType(mkField("Intff", intType()))
480	for _, test := range []encodeTest{
481		{
482			"Named struct-type field.",
483			struct {
484				Intf    int
485				Structf structf
486			}{10, structf{10}},
487			listProto(intProto(10), listProto(intProto(10))),
488			structType(
489				mkField("Intf", intType()),
490				mkField("Structf", structfType)),
491		},
492		{
493			"Unnamed struct-type field.",
494			struct {
495				Intf    int
496				Structf structf `spanner:""`
497			}{10, structf{10}},
498			listProto(intProto(10), listProto(intProto(10))),
499			structType(
500				mkField("Intf", intType()),
501				mkField("", structfType)),
502		},
503		{
504			"Duplicate struct-typed field.",
505			struct {
506				Structf1 structf `spanner:""`
507				Structf2 structf `spanner:""`
508			}{structf{10}, structf{20}},
509			listProto(listProto(intProto(10)), listProto(intProto(20))),
510			structType(
511				mkField("", structfType),
512				mkField("", structfType)),
513		},
514		{
515			"Null struct-typed field.",
516			struct {
517				Intf    int
518				Structf *structf
519			}{10, nil},
520			listProto(intProto(10), nullProto()),
521			structType(
522				mkField("Intf", intType()),
523				mkField("Structf", structfType)),
524		},
525		{
526			"Empty struct-typed field.",
527			struct {
528				Intf    int
529				Structf struct{}
530			}{10, struct{}{}},
531			listProto(intProto(10), listProto([]*proto3.Value{}...)),
532			structType(
533				mkField("Intf", intType()),
534				mkField("Structf", structType([]*sppb.StructType_Field{}...))),
535		},
536	} {
537		encodeStructValue(test, t)
538	}
539}
540
541func TestEncodeStructValueFieldNames(t *testing.T) {
542	type embedded struct {
543		B bool
544	}
545
546	for _, test := range []encodeTest{
547		{
548			"Duplicate fields.",
549			struct {
550				Field1    int `spanner:"field"`
551				DupField1 int `spanner:"field"`
552			}{10, 20},
553			listProto(intProto(10), intProto(20)),
554			structType(
555				mkField("field", intType()),
556				mkField("field", intType())),
557		},
558		{
559			"Duplicate Fields (different types).",
560			struct {
561				IntField    int    `spanner:"field"`
562				StringField string `spanner:"field"`
563			}{10, "abc"},
564			listProto(intProto(10), stringProto("abc")),
565			structType(
566				mkField("field", intType()),
567				mkField("field", stringType())),
568		},
569		{
570			"Duplicate unnamed fields.",
571			struct {
572				Dup  int `spanner:""`
573				Dup1 int `spanner:""`
574			}{10, 20},
575			listProto(intProto(10), intProto(20)),
576			structType(
577				mkField("", intType()),
578				mkField("", intType())),
579		},
580		{
581			"Named and unnamed fields.",
582			struct {
583				Field  string
584				Field1 int    `spanner:""`
585				Field2 string `spanner:"field"`
586			}{"abc", 10, "def"},
587			listProto(stringProto("abc"), intProto(10), stringProto("def")),
588			structType(
589				mkField("Field", stringType()),
590				mkField("", intType()),
591				mkField("field", stringType())),
592		},
593		{
594			"Ignored unexported fields.",
595			struct {
596				Field  int
597				field  bool
598				Field1 string `spanner:"field"`
599			}{10, false, "abc"},
600			listProto(intProto(10), stringProto("abc")),
601			structType(
602				mkField("Field", intType()),
603				mkField("field", stringType())),
604		},
605		{
606			"Ignored unexported struct/slice fields.",
607			struct {
608				a      []*embedded
609				b      []embedded
610				c      embedded
611				d      *embedded
612				Field1 string `spanner:"field"`
613			}{nil, nil, embedded{}, nil, "def"},
614			listProto(stringProto("def")),
615			structType(
616				mkField("field", stringType())),
617		},
618	} {
619		encodeStructValue(test, t)
620	}
621}
622
623func TestEncodeStructValueBasicFields(t *testing.T) {
624	type CustomString string
625	type CustomBytes []byte
626	type CustomInt64 int64
627	type CustomBool bool
628	type CustomFloat64 float64
629	type CustomTime time.Time
630	type CustomDate civil.Date
631
632	type CustomNullString NullString
633	type CustomNullInt64 NullInt64
634	type CustomNullBool NullBool
635	type CustomNullFloat64 NullFloat64
636	type CustomNullTime NullTime
637	type CustomNullDate NullDate
638
639	sValue := "abc"
640	iValue := int64(300)
641	bValue := false
642	fValue := 3.45
643	tValue := t1
644	dValue := d1
645
646	StructTypeProto := structType(
647		mkField("Stringf", stringType()),
648		mkField("Intf", intType()),
649		mkField("Boolf", boolType()),
650		mkField("Floatf", floatType()),
651		mkField("Bytef", bytesType()),
652		mkField("Timef", timeType()),
653		mkField("Datef", dateType()))
654
655	for _, test := range []encodeTest{
656		{
657			"Basic types.",
658			struct {
659				Stringf string
660				Intf    int
661				Boolf   bool
662				Floatf  float64
663				Bytef   []byte
664				Timef   time.Time
665				Datef   civil.Date
666			}{"abc", 300, false, 3.45, []byte("foo"), t1, d1},
667			listProto(
668				stringProto("abc"),
669				intProto(300),
670				boolProto(false),
671				floatProto(3.45),
672				bytesProto([]byte("foo")),
673				timeProto(t1),
674				dateProto(d1)),
675			StructTypeProto,
676		},
677		{
678			"Pointers to basic types.",
679			struct {
680				Stringf *string
681				Intf    *int64
682				Boolf   *bool
683				Floatf  *float64
684				Bytef   []byte
685				Timef   *time.Time
686				Datef   *civil.Date
687			}{&sValue, &iValue, &bValue, &fValue, []byte("foo"), &tValue, &dValue},
688			listProto(
689				stringProto("abc"),
690				intProto(300),
691				boolProto(false),
692				floatProto(3.45),
693				bytesProto([]byte("foo")),
694				timeProto(t1),
695				dateProto(d1)),
696			StructTypeProto,
697		},
698		{
699			"Pointers to basic types with null values.",
700			struct {
701				Stringf *string
702				Intf    *int64
703				Boolf   *bool
704				Floatf  *float64
705				Bytef   []byte
706				Timef   *time.Time
707				Datef   *civil.Date
708			}{nil, nil, nil, nil, nil, nil, nil},
709			listProto(
710				nullProto(),
711				nullProto(),
712				nullProto(),
713				nullProto(),
714				nullProto(),
715				nullProto(),
716				nullProto()),
717			StructTypeProto,
718		},
719		{
720			"Basic custom types.",
721			struct {
722				Stringf CustomString
723				Intf    CustomInt64
724				Boolf   CustomBool
725				Floatf  CustomFloat64
726				Bytef   CustomBytes
727				Timef   CustomTime
728				Datef   CustomDate
729			}{"abc", 300, false, 3.45, []byte("foo"), CustomTime(t1), CustomDate(d1)},
730			listProto(
731				stringProto("abc"),
732				intProto(300),
733				boolProto(false),
734				floatProto(3.45),
735				bytesProto([]byte("foo")),
736				timeProto(t1),
737				dateProto(d1)),
738			StructTypeProto,
739		},
740		{
741			"Basic types null values.",
742			struct {
743				Stringf NullString
744				Intf    NullInt64
745				Boolf   NullBool
746				Floatf  NullFloat64
747				Bytef   []byte
748				Timef   NullTime
749				Datef   NullDate
750			}{
751				NullString{"abc", false},
752				NullInt64{4, false},
753				NullBool{false, false},
754				NullFloat64{5.6, false},
755				nil,
756				NullTime{t1, false},
757				NullDate{d1, false},
758			},
759			listProto(
760				nullProto(),
761				nullProto(),
762				nullProto(),
763				nullProto(),
764				nullProto(),
765				nullProto(),
766				nullProto()),
767			StructTypeProto,
768		},
769		{
770			"Basic custom types null values.",
771			struct {
772				Stringf CustomNullString
773				Intf    CustomNullInt64
774				Boolf   CustomNullBool
775				Floatf  CustomNullFloat64
776				Bytef   CustomBytes
777				Timef   CustomNullTime
778				Datef   CustomNullDate
779			}{
780				CustomNullString{"abc", false},
781				CustomNullInt64{4, false},
782				CustomNullBool{false, false},
783				CustomNullFloat64{5.6, false},
784				nil,
785				CustomNullTime{t1, false},
786				CustomNullDate{d1, false},
787			},
788			listProto(
789				nullProto(),
790				nullProto(),
791				nullProto(),
792				nullProto(),
793				nullProto(),
794				nullProto(),
795				nullProto()),
796			StructTypeProto,
797		},
798	} {
799		encodeStructValue(test, t)
800	}
801}
802
803func TestEncodeStructValueArrayFields(t *testing.T) {
804	type CustomString string
805	type CustomBytes []byte
806	type CustomInt64 int64
807	type CustomBool bool
808	type CustomFloat64 float64
809	type CustomTime time.Time
810	type CustomDate civil.Date
811
812	type CustomNullString NullString
813	type CustomNullInt64 NullInt64
814	type CustomNullBool NullBool
815	type CustomNullFloat64 NullFloat64
816	type CustomNullTime NullTime
817	type CustomNullDate NullDate
818
819	sValue := "def"
820	var sNilPtr *string
821	iValue := int64(68)
822	var iNilPtr *int64
823	bValue := true
824	var bNilPtr *bool
825	fValue := 3.14
826	var fNilPtr *float64
827	tValue := t1
828	var tNilPtr *time.Time
829	dValue := d1
830	var dNilPtr *civil.Date
831
832	StructTypeProto := structType(
833		mkField("Stringf", listType(stringType())),
834		mkField("Intf", listType(intType())),
835		mkField("Int64f", listType(intType())),
836		mkField("Boolf", listType(boolType())),
837		mkField("Floatf", listType(floatType())),
838		mkField("Bytef", listType(bytesType())),
839		mkField("Timef", listType(timeType())),
840		mkField("Datef", listType(dateType())))
841
842	for _, test := range []encodeTest{
843		{
844			"Arrays of basic types with non-nullable elements",
845			struct {
846				Stringf []string
847				Intf    []int
848				Int64f  []int64
849				Boolf   []bool
850				Floatf  []float64
851				Bytef   [][]byte
852				Timef   []time.Time
853				Datef   []civil.Date
854			}{
855				[]string{"abc", "def"},
856				[]int{4, 67},
857				[]int64{5, 68},
858				[]bool{false, true},
859				[]float64{3.45, 0.93},
860				[][]byte{[]byte("foo"), nil},
861				[]time.Time{t1, t2},
862				[]civil.Date{d1, d2},
863			},
864			listProto(
865				listProto(stringProto("abc"), stringProto("def")),
866				listProto(intProto(4), intProto(67)),
867				listProto(intProto(5), intProto(68)),
868				listProto(boolProto(false), boolProto(true)),
869				listProto(floatProto(3.45), floatProto(0.93)),
870				listProto(bytesProto([]byte("foo")), nullProto()),
871				listProto(timeProto(t1), timeProto(t2)),
872				listProto(dateProto(d1), dateProto(d2))),
873			StructTypeProto,
874		},
875		{
876			"Arrays of basic custom types with non-nullable elements",
877			struct {
878				Stringf []CustomString
879				Intf    []CustomInt64
880				Int64f  []CustomInt64
881				Boolf   []CustomBool
882				Floatf  []CustomFloat64
883				Bytef   []CustomBytes
884				Timef   []CustomTime
885				Datef   []CustomDate
886			}{
887				[]CustomString{"abc", "def"},
888				[]CustomInt64{4, 67},
889				[]CustomInt64{5, 68},
890				[]CustomBool{false, true},
891				[]CustomFloat64{3.45, 0.93},
892				[]CustomBytes{[]byte("foo"), nil},
893				[]CustomTime{CustomTime(t1), CustomTime(t2)},
894				[]CustomDate{CustomDate(d1), CustomDate(d2)},
895			},
896			listProto(
897				listProto(stringProto("abc"), stringProto("def")),
898				listProto(intProto(4), intProto(67)),
899				listProto(intProto(5), intProto(68)),
900				listProto(boolProto(false), boolProto(true)),
901				listProto(floatProto(3.45), floatProto(0.93)),
902				listProto(bytesProto([]byte("foo")), nullProto()),
903				listProto(timeProto(t1), timeProto(t2)),
904				listProto(dateProto(d1), dateProto(d2))),
905			StructTypeProto,
906		},
907		{
908			"Arrays of basic types with nullable elements.",
909			struct {
910				Stringf []NullString
911				Intf    []NullInt64
912				Int64f  []NullInt64
913				Boolf   []NullBool
914				Floatf  []NullFloat64
915				Bytef   [][]byte
916				Timef   []NullTime
917				Datef   []NullDate
918			}{
919				[]NullString{{"abc", false}, {"def", true}},
920				[]NullInt64{{4, false}, {67, true}},
921				[]NullInt64{{5, false}, {68, true}},
922				[]NullBool{{true, false}, {false, true}},
923				[]NullFloat64{{3.45, false}, {0.93, true}},
924				[][]byte{[]byte("foo"), nil},
925				[]NullTime{{t1, false}, {t2, true}},
926				[]NullDate{{d1, false}, {d2, true}},
927			},
928			listProto(
929				listProto(nullProto(), stringProto("def")),
930				listProto(nullProto(), intProto(67)),
931				listProto(nullProto(), intProto(68)),
932				listProto(nullProto(), boolProto(false)),
933				listProto(nullProto(), floatProto(0.93)),
934				listProto(bytesProto([]byte("foo")), nullProto()),
935				listProto(nullProto(), timeProto(t2)),
936				listProto(nullProto(), dateProto(d2))),
937			StructTypeProto,
938		},
939		{
940			"Arrays of pointers to basic types with nullable elements.",
941			struct {
942				Stringf []*string
943				Intf    []*int64
944				Int64f  []*int64
945				Boolf   []*bool
946				Floatf  []*float64
947				Bytef   [][]byte
948				Timef   []*time.Time
949				Datef   []*civil.Date
950			}{
951				[]*string{sNilPtr, &sValue},
952				[]*int64{iNilPtr, &iValue},
953				[]*int64{iNilPtr, &iValue},
954				[]*bool{bNilPtr, &bValue},
955				[]*float64{fNilPtr, &fValue},
956				[][]byte{[]byte("foo"), nil},
957				[]*time.Time{tNilPtr, &tValue},
958				[]*civil.Date{dNilPtr, &dValue},
959			},
960			listProto(
961				listProto(nullProto(), stringProto("def")),
962				listProto(nullProto(), intProto(68)),
963				listProto(nullProto(), intProto(68)),
964				listProto(nullProto(), boolProto(true)),
965				listProto(nullProto(), floatProto(3.14)),
966				listProto(bytesProto([]byte("foo")), nullProto()),
967				listProto(nullProto(), timeProto(t1)),
968				listProto(nullProto(), dateProto(d1))),
969			StructTypeProto,
970		},
971		{
972			"Arrays of basic custom types with nullable elements.",
973			struct {
974				Stringf []CustomNullString
975				Intf    []CustomNullInt64
976				Int64f  []CustomNullInt64
977				Boolf   []CustomNullBool
978				Floatf  []CustomNullFloat64
979				Bytef   []CustomBytes
980				Timef   []CustomNullTime
981				Datef   []CustomNullDate
982			}{
983				[]CustomNullString{{"abc", false}, {"def", true}},
984				[]CustomNullInt64{{4, false}, {67, true}},
985				[]CustomNullInt64{{5, false}, {68, true}},
986				[]CustomNullBool{{true, false}, {false, true}},
987				[]CustomNullFloat64{{3.45, false}, {0.93, true}},
988				[]CustomBytes{[]byte("foo"), nil},
989				[]CustomNullTime{{t1, false}, {t2, true}},
990				[]CustomNullDate{{d1, false}, {d2, true}},
991			},
992			listProto(
993				listProto(nullProto(), stringProto("def")),
994				listProto(nullProto(), intProto(67)),
995				listProto(nullProto(), intProto(68)),
996				listProto(nullProto(), boolProto(false)),
997				listProto(nullProto(), floatProto(0.93)),
998				listProto(bytesProto([]byte("foo")), nullProto()),
999				listProto(nullProto(), timeProto(t2)),
1000				listProto(nullProto(), dateProto(d2))),
1001			StructTypeProto,
1002		},
1003		{
1004			"Null arrays of basic types.",
1005			struct {
1006				Stringf []NullString
1007				Intf    []NullInt64
1008				Int64f  []NullInt64
1009				Boolf   []NullBool
1010				Floatf  []NullFloat64
1011				Bytef   [][]byte
1012				Timef   []NullTime
1013				Datef   []NullDate
1014			}{
1015				nil,
1016				nil,
1017				nil,
1018				nil,
1019				nil,
1020				nil,
1021				nil,
1022				nil,
1023			},
1024			listProto(
1025				nullProto(),
1026				nullProto(),
1027				nullProto(),
1028				nullProto(),
1029				nullProto(),
1030				nullProto(),
1031				nullProto(),
1032				nullProto()),
1033			StructTypeProto,
1034		},
1035		{
1036			"Null arrays of basic custom types.",
1037			struct {
1038				Stringf []CustomNullString
1039				Intf    []CustomNullInt64
1040				Int64f  []CustomNullInt64
1041				Boolf   []CustomNullBool
1042				Floatf  []CustomNullFloat64
1043				Bytef   []CustomBytes
1044				Timef   []CustomNullTime
1045				Datef   []CustomNullDate
1046			}{
1047				nil,
1048				nil,
1049				nil,
1050				nil,
1051				nil,
1052				nil,
1053				nil,
1054				nil,
1055			},
1056			listProto(
1057				nullProto(),
1058				nullProto(),
1059				nullProto(),
1060				nullProto(),
1061				nullProto(),
1062				nullProto(),
1063				nullProto(),
1064				nullProto()),
1065			StructTypeProto,
1066		},
1067	} {
1068		encodeStructValue(test, t)
1069	}
1070}
1071
1072// Test decoding Values.
1073func TestDecodeValue(t *testing.T) {
1074	type CustomString string
1075	type CustomBytes []byte
1076	type CustomInt64 int64
1077	type CustomBool bool
1078	type CustomFloat64 float64
1079	type CustomTime time.Time
1080	type CustomDate civil.Date
1081
1082	type CustomNullString NullString
1083	type CustomNullInt64 NullInt64
1084	type CustomNullBool NullBool
1085	type CustomNullFloat64 NullFloat64
1086	type CustomNullTime NullTime
1087	type CustomNullDate NullDate
1088
1089	// Pointer values.
1090	sValue := "abc"
1091	var sNilPtr *string
1092	s2Value := "bcd"
1093
1094	iValue := int64(15)
1095	var iNilPtr *int64
1096	i1Value := int64(91)
1097	i2Value := int64(87)
1098
1099	bValue := true
1100	var bNilPtr *bool
1101	b2Value := false
1102
1103	fValue := 3.14
1104	var fNilPtr *float64
1105	f2Value := 6.626
1106
1107	tValue := t1
1108	var tNilPtr *time.Time
1109	t2Value := t2
1110
1111	dValue := d1
1112	var dNilPtr *civil.Date
1113	d2Value := d2
1114
1115	for _, test := range []struct {
1116		desc      string
1117		proto     *proto3.Value
1118		protoType *sppb.Type
1119		want      interface{}
1120		wantErr   bool
1121	}{
1122		// STRING
1123		{desc: "decode STRING to string", proto: stringProto("abc"), protoType: stringType(), want: "abc"},
1124		{desc: "decode NULL to string", proto: nullProto(), protoType: stringType(), want: "abc", wantErr: true},
1125		{desc: "decode STRING to *string", proto: stringProto("abc"), protoType: stringType(), want: &sValue},
1126		{desc: "decode NULL to *string", proto: nullProto(), protoType: stringType(), want: sNilPtr},
1127		{desc: "decode STRING to NullString", proto: stringProto("abc"), protoType: stringType(), want: NullString{"abc", true}},
1128		{desc: "decode NULL to NullString", proto: nullProto(), protoType: stringType(), want: NullString{}},
1129		// STRING ARRAY with []NullString
1130		{desc: "decode ARRAY<STRING> to []NullString", proto: listProto(stringProto("abc"), nullProto(), stringProto("bcd")), protoType: listType(stringType()), want: []NullString{{"abc", true}, {}, {"bcd", true}}},
1131		{desc: "decode NULL to []NullString", proto: nullProto(), protoType: listType(stringType()), want: []NullString(nil)},
1132		// STRING ARRAY with []string
1133		{desc: "decode ARRAY<STRING> to []string", proto: listProto(stringProto("abc"), stringProto("bcd")), protoType: listType(stringType()), want: []string{"abc", "bcd"}},
1134		// STRING ARRAY with []*string
1135		{desc: "decode ARRAY<STRING> to []*string", proto: listProto(stringProto("abc"), nullProto(), stringProto("bcd")), protoType: listType(stringType()), want: []*string{&sValue, sNilPtr, &s2Value}},
1136		{desc: "decode NULL to []*string", proto: nullProto(), protoType: listType(stringType()), want: []*string(nil)},
1137		// BYTES
1138		{desc: "decode BYTES to []byte", proto: bytesProto([]byte("ab")), protoType: bytesType(), want: []byte("ab")},
1139		{desc: "decode NULL to []byte", proto: nullProto(), protoType: bytesType(), want: []byte(nil)},
1140		// BYTES ARRAY
1141		{desc: "decode ARRAY<BYTES> to [][]byte", proto: listProto(bytesProto([]byte("ab")), nullProto()), protoType: listType(bytesType()), want: [][]byte{[]byte("ab"), nil}},
1142		{desc: "decode NULL to [][]byte", proto: nullProto(), protoType: listType(bytesType()), want: [][]byte(nil)},
1143		//INT64
1144		{desc: "decode INT64 to int64", proto: intProto(15), protoType: intType(), want: int64(15)},
1145		{desc: "decode NULL to int64", proto: nullProto(), protoType: intType(), want: int64(0), wantErr: true},
1146		{desc: "decode INT64 to *int64", proto: intProto(15), protoType: intType(), want: &iValue},
1147		{desc: "decode NULL to *int64", proto: nullProto(), protoType: intType(), want: iNilPtr},
1148		{desc: "decode INT64 to NullInt64", proto: intProto(15), protoType: intType(), want: NullInt64{15, true}},
1149		{desc: "decode NULL to NullInt64", proto: nullProto(), protoType: intType(), want: NullInt64{}},
1150		// INT64 ARRAY with []NullInt64
1151		{desc: "decode ARRAY<INT64> to []NullInt64", proto: listProto(intProto(91), nullProto(), intProto(87)), protoType: listType(intType()), want: []NullInt64{{91, true}, {}, {87, true}}},
1152		{desc: "decode NULL to []NullInt64", proto: nullProto(), protoType: listType(intType()), want: []NullInt64(nil)},
1153		// INT64 ARRAY with []int64
1154		{desc: "decode ARRAY<INT64> to []int64", proto: listProto(intProto(91), intProto(87)), protoType: listType(intType()), want: []int64{91, 87}},
1155		// INT64 ARRAY with []*int64
1156		{desc: "decode ARRAY<INT64> to []*int64", proto: listProto(intProto(91), nullProto(), intProto(87)), protoType: listType(intType()), want: []*int64{&i1Value, nil, &i2Value}},
1157		{desc: "decode NULL to []*int64", proto: nullProto(), protoType: listType(intType()), want: []*int64(nil)},
1158		// BOOL
1159		{desc: "decode BOOL to bool", proto: boolProto(true), protoType: boolType(), want: true},
1160		{desc: "decode NULL to bool", proto: nullProto(), protoType: boolType(), want: true, wantErr: true},
1161		{desc: "decode BOOL to *bool", proto: boolProto(true), protoType: boolType(), want: &bValue},
1162		{desc: "decode NULL to *bool", proto: nullProto(), protoType: boolType(), want: bNilPtr},
1163		{desc: "decode BOOL to NullBool", proto: boolProto(true), protoType: boolType(), want: NullBool{true, true}},
1164		{desc: "decode BOOL to NullBool", proto: nullProto(), protoType: boolType(), want: NullBool{}},
1165		// BOOL ARRAY with []NullBool
1166		{desc: "decode ARRAY<BOOL> to []NullBool", proto: listProto(boolProto(true), boolProto(false), nullProto()), protoType: listType(boolType()), want: []NullBool{{true, true}, {false, true}, {}}},
1167		{desc: "decode NULL to []NullBool", proto: nullProto(), protoType: listType(boolType()), want: []NullBool(nil)},
1168		// BOOL ARRAY with []bool
1169		{desc: "decode ARRAY<BOOL> to []bool", proto: listProto(boolProto(true), boolProto(false)), protoType: listType(boolType()), want: []bool{true, false}},
1170		// BOOL ARRAY with []*bool
1171		{desc: "decode ARRAY<BOOL> to []*bool", proto: listProto(boolProto(true), nullProto(), boolProto(false)), protoType: listType(boolType()), want: []*bool{&bValue, bNilPtr, &b2Value}},
1172		{desc: "decode NULL to []*bool", proto: nullProto(), protoType: listType(boolType()), want: []*bool(nil)},
1173		// FLOAT64
1174		{desc: "decode FLOAT64 to float64", proto: floatProto(3.14), protoType: floatType(), want: 3.14},
1175		{desc: "decode NULL to float64", proto: nullProto(), protoType: floatType(), want: 0.00, wantErr: true},
1176		{desc: "decode FLOAT64 to *float64", proto: floatProto(3.14), protoType: floatType(), want: &fValue},
1177		{desc: "decode NULL to *float64", proto: nullProto(), protoType: floatType(), want: fNilPtr},
1178		{desc: "decode FLOAT64 to NullFloat64", proto: floatProto(3.14), protoType: floatType(), want: NullFloat64{3.14, true}},
1179		{desc: "decode NULL to NullFloat64", proto: nullProto(), protoType: floatType(), want: NullFloat64{}},
1180		// FLOAT64 ARRAY with []NullFloat64
1181		{desc: "decode ARRAY<FLOAT64> to []NullFloat64", proto: listProto(floatProto(math.Inf(1)), floatProto(math.Inf(-1)), nullProto(), floatProto(3.1)), protoType: listType(floatType()), want: []NullFloat64{{math.Inf(1), true}, {math.Inf(-1), true}, {}, {3.1, true}}},
1182		{desc: "decode NULL to []NullFloat64", proto: nullProto(), protoType: listType(floatType()), want: []NullFloat64(nil)},
1183		// FLOAT64 ARRAY with []float64
1184		{desc: "decode ARRAY<FLOAT64> to []float64", proto: listProto(floatProto(math.Inf(1)), floatProto(math.Inf(-1)), floatProto(3.1)), protoType: listType(floatType()), want: []float64{math.Inf(1), math.Inf(-1), 3.1}},
1185		// FLOAT64 ARRAY with []NullFloat64
1186		{desc: "decode ARRAY<FLOAT64> to []*float64", proto: listProto(floatProto(fValue), nullProto(), floatProto(f2Value)), protoType: listType(floatType()), want: []*float64{&fValue, nil, &f2Value}},
1187		{desc: "decode NULL to []*float64", proto: nullProto(), protoType: listType(floatType()), want: []*float64(nil)},
1188		// TIMESTAMP
1189		{desc: "decode TIMESTAMP to time.Time", proto: timeProto(t1), protoType: timeType(), want: t1},
1190		{desc: "decode TIMESTAMP to NullTime", proto: timeProto(t1), protoType: timeType(), want: NullTime{t1, true}},
1191		{desc: "decode NULL to NullTime", proto: nullProto(), protoType: timeType(), want: NullTime{}},
1192		{desc: "decode TIMESTAMP to *time.Time", proto: timeProto(t1), protoType: timeType(), want: &tValue},
1193		{desc: "decode NULL to *time.Time", proto: nullProto(), protoType: timeType(), want: tNilPtr},
1194		{desc: "decode INT64 to time.Time", proto: intProto(7), protoType: timeType(), want: time.Time{}, wantErr: true},
1195		// TIMESTAMP ARRAY with []NullTime
1196		{desc: "decode ARRAY<TIMESTAMP> to []NullTime", proto: listProto(timeProto(t1), timeProto(t2), timeProto(t3), nullProto()), protoType: listType(timeType()), want: []NullTime{{t1, true}, {t2, true}, {t3, true}, {}}},
1197		{desc: "decode NULL to []NullTime", proto: nullProto(), protoType: listType(timeType()), want: []NullTime(nil)},
1198		// TIMESTAMP ARRAY with []time.Time
1199		{desc: "decode ARRAY<TIMESTAMP> to []time.Time", proto: listProto(timeProto(t1), timeProto(t2), timeProto(t3)), protoType: listType(timeType()), want: []time.Time{t1, t2, t3}},
1200		// TIMESTAMP ARRAY with []*time.Time
1201		{desc: "decode ARRAY<TIMESTAMP> to []*time.Time", proto: listProto(timeProto(t1), nullProto(), timeProto(t2)), protoType: listType(timeType()), want: []*time.Time{&tValue, nil, &t2Value}},
1202		{desc: "decode NULL to []*time.Time", proto: nullProto(), protoType: listType(timeType()), want: []*time.Time(nil)},
1203		// DATE
1204		{desc: "decode DATE to civil.Date", proto: dateProto(d1), protoType: dateType(), want: d1},
1205		{desc: "decode DATE to NullDate", proto: dateProto(d1), protoType: dateType(), want: NullDate{d1, true}},
1206		{desc: "decode NULL to NullDate", proto: nullProto(), protoType: dateType(), want: NullDate{}},
1207		{desc: "decode DATE to *civil.Date", proto: dateProto(d1), protoType: dateType(), want: &dValue},
1208		{desc: "decode NULL to *civil.Date", proto: nullProto(), protoType: dateType(), want: dNilPtr},
1209		// DATE ARRAY with []NullDate
1210		{desc: "decode ARRAY<DATE> to []NullDate", proto: listProto(dateProto(d1), dateProto(d2), nullProto()), protoType: listType(dateType()), want: []NullDate{{d1, true}, {d2, true}, {}}},
1211		{desc: "decode NULL to []NullDate", proto: nullProto(), protoType: listType(dateType()), want: []NullDate(nil)},
1212		// DATE ARRAY with []civil.Date
1213		{desc: "decode ARRAY<DATE> to []civil.Date", proto: listProto(dateProto(d1), dateProto(d2)), protoType: listType(dateType()), want: []civil.Date{d1, d2}},
1214		// DATE ARRAY with []NullDate
1215		{desc: "decode ARRAY<DATE> to []*civil.Date", proto: listProto(dateProto(d1), nullProto(), dateProto(d2)), protoType: listType(dateType()), want: []*civil.Date{&dValue, nil, &d2Value}},
1216		{desc: "decode NULL to []*civil.Date", proto: nullProto(), protoType: listType(dateType()), want: []*civil.Date(nil)},
1217		// STRUCT ARRAY
1218		// STRUCT schema is equal to the following Go struct:
1219		// type s struct {
1220		//     Col1 NullInt64
1221		//     Col2 []struct {
1222		//         SubCol1 float64
1223		//         SubCol2 string
1224		//     }
1225		// }
1226		{
1227			desc: "decode ARRAY<STRUCT> to []NullRow",
1228			proto: listProto(
1229				listProto(
1230					intProto(3),
1231					listProto(
1232						listProto(floatProto(3.14), stringProto("this")),
1233						listProto(floatProto(0.57), stringProto("siht")),
1234					),
1235				),
1236				listProto(
1237					nullProto(),
1238					nullProto(),
1239				),
1240				nullProto(),
1241			),
1242			protoType: listType(
1243				structType(
1244					mkField("Col1", intType()),
1245					mkField(
1246						"Col2",
1247						listType(
1248							structType(
1249								mkField("SubCol1", floatType()),
1250								mkField("SubCol2", stringType()),
1251							),
1252						),
1253					),
1254				),
1255			),
1256			want: []NullRow{
1257				{
1258					Row: Row{
1259						fields: []*sppb.StructType_Field{
1260							mkField("Col1", intType()),
1261							mkField(
1262								"Col2",
1263								listType(
1264									structType(
1265										mkField("SubCol1", floatType()),
1266										mkField("SubCol2", stringType()),
1267									),
1268								),
1269							),
1270						},
1271						vals: []*proto3.Value{
1272							intProto(3),
1273							listProto(
1274								listProto(floatProto(3.14), stringProto("this")),
1275								listProto(floatProto(0.57), stringProto("siht")),
1276							),
1277						},
1278					},
1279					Valid: true,
1280				},
1281				{
1282					Row: Row{
1283						fields: []*sppb.StructType_Field{
1284							mkField("Col1", intType()),
1285							mkField(
1286								"Col2",
1287								listType(
1288									structType(
1289										mkField("SubCol1", floatType()),
1290										mkField("SubCol2", stringType()),
1291									),
1292								),
1293							),
1294						},
1295						vals: []*proto3.Value{
1296							nullProto(),
1297							nullProto(),
1298						},
1299					},
1300					Valid: true,
1301				},
1302				{},
1303			},
1304		},
1305		{
1306			desc: "decode ARRAY<STRUCT> to []*struct",
1307			proto: listProto(
1308				listProto(
1309					intProto(3),
1310					listProto(
1311						listProto(floatProto(3.14), stringProto("this")),
1312						listProto(floatProto(0.57), stringProto("siht")),
1313					),
1314				),
1315				listProto(
1316					nullProto(),
1317					nullProto(),
1318				),
1319				nullProto(),
1320			),
1321			protoType: listType(
1322				structType(
1323					mkField("Col1", intType()),
1324					mkField(
1325						"Col2",
1326						listType(
1327							structType(
1328								mkField("SubCol1", floatType()),
1329								mkField("SubCol2", stringType()),
1330							),
1331						),
1332					),
1333				),
1334			),
1335			want: []*struct {
1336				Col1      NullInt64
1337				StructCol []*struct {
1338					SubCol1 NullFloat64
1339					SubCol2 string
1340				} `spanner:"Col2"`
1341			}{
1342				{
1343					Col1: NullInt64{3, true},
1344					StructCol: []*struct {
1345						SubCol1 NullFloat64
1346						SubCol2 string
1347					}{
1348						{
1349							SubCol1: NullFloat64{3.14, true},
1350							SubCol2: "this",
1351						},
1352						{
1353							SubCol1: NullFloat64{0.57, true},
1354							SubCol2: "siht",
1355						},
1356					},
1357				},
1358				{
1359					Col1: NullInt64{},
1360					StructCol: []*struct {
1361						SubCol1 NullFloat64
1362						SubCol2 string
1363					}(nil),
1364				},
1365				nil,
1366			},
1367		},
1368		// GenericColumnValue
1369		{desc: "decode STRING to GenericColumnValue", proto: stringProto("abc"), protoType: stringType(), want: GenericColumnValue{stringType(), stringProto("abc")}},
1370		{desc: "decode NULL to GenericColumnValue", proto: nullProto(), protoType: stringType(), want: GenericColumnValue{stringType(), nullProto()}},
1371		// not actually valid (stringProto inside int list), but demonstrates pass-through.
1372		{desc: "decode ARRAY<INT64> to GenericColumnValue", proto: listProto(intProto(5), nullProto(), stringProto("bcd")), protoType: listType(intType()), want: GenericColumnValue{Type: listType(intType()), Value: listProto(intProto(5), nullProto(), stringProto("bcd"))}},
1373
1374		// Custom base types.
1375		{desc: "decode STRING to CustomString", proto: stringProto("bar"), protoType: stringType(), want: CustomString("bar")},
1376		{desc: "decode BYTES to CustomBytes", proto: bytesProto([]byte("ab")), protoType: bytesType(), want: CustomBytes("ab")},
1377		{desc: "decode INT64 to CustomInt64", proto: intProto(-100), protoType: intType(), want: CustomInt64(-100)},
1378		{desc: "decode BOOL to CustomBool", proto: boolProto(true), protoType: boolType(), want: CustomBool(true)},
1379		{desc: "decode FLOAT64 to CustomFloat64", proto: floatProto(6.626), protoType: floatType(), want: CustomFloat64(6.626)},
1380		{desc: "decode TIMESTAMP to CustomTimestamp", proto: timeProto(t1), protoType: timeType(), want: CustomTime(t1)},
1381		{desc: "decode DATE to CustomDate", proto: dateProto(d1), protoType: dateType(), want: CustomDate(d1)},
1382
1383		{desc: "decode NULL to CustomString", proto: nullProto(), protoType: stringType(), want: CustomString(""), wantErr: true},
1384		{desc: "decode NULL to CustomBytes", proto: nullProto(), protoType: bytesType(), want: CustomBytes(nil)},
1385		{desc: "decode NULL to CustomInt64", proto: nullProto(), protoType: intType(), want: CustomInt64(0), wantErr: true},
1386		{desc: "decode NULL to CustomBool", proto: nullProto(), protoType: boolType(), want: CustomBool(false), wantErr: true},
1387		{desc: "decode NULL to CustomFloat64", proto: nullProto(), protoType: floatType(), want: CustomFloat64(0), wantErr: true},
1388		{desc: "decode NULL to CustomTime", proto: nullProto(), protoType: timeType(), want: CustomTime{}, wantErr: true},
1389		{desc: "decode NULL to CustomDate", proto: nullProto(), protoType: dateType(), want: CustomDate{}, wantErr: true},
1390
1391		{desc: "decode STRING to CustomNullString", proto: stringProto("bar"), protoType: stringType(), want: CustomNullString{"bar", true}},
1392		{desc: "decode INT64 to CustomNullInt64", proto: intProto(-100), protoType: intType(), want: CustomNullInt64{-100, true}},
1393		{desc: "decode BOOL to CustomNullBool", proto: boolProto(true), protoType: boolType(), want: CustomNullBool{true, true}},
1394		{desc: "decode FLOAT64 to CustomNullFloat64", proto: floatProto(6.626), protoType: floatType(), want: CustomNullFloat64{6.626, true}},
1395		{desc: "decode TIMESTAMP to CustomNullTime", proto: timeProto(t1), protoType: timeType(), want: CustomNullTime{t1, true}},
1396		{desc: "decode DATE to CustomNullDate", proto: dateProto(d1), protoType: dateType(), want: CustomNullDate{d1, true}},
1397
1398		{desc: "decode NULL to CustomNullString", proto: nullProto(), protoType: stringType(), want: CustomNullString{}},
1399		{desc: "decode NULL to CustomNullInt64", proto: nullProto(), protoType: intType(), want: CustomNullInt64{}},
1400		{desc: "decode NULL to CustomNullBool", proto: nullProto(), protoType: boolType(), want: CustomNullBool{}},
1401		{desc: "decode NULL to CustomNullFloat64", proto: nullProto(), protoType: floatType(), want: CustomNullFloat64{}},
1402		{desc: "decode NULL to CustomNullTime", proto: nullProto(), protoType: timeType(), want: CustomNullTime{}},
1403		{desc: "decode NULL to CustomNullDate", proto: nullProto(), protoType: dateType(), want: CustomNullDate{}},
1404
1405		// STRING ARRAY
1406		{desc: "decode NULL to []CustomString", proto: nullProto(), protoType: listType(stringType()), want: []CustomString(nil)},
1407		{desc: "decode ARRAY<STRING> to []CustomString", proto: listProto(stringProto("abc"), stringProto("bcd")), protoType: listType(stringType()), want: []CustomString{"abc", "bcd"}},
1408		{desc: "decode ARRAY<STRING> with NULL values to []CustomString", proto: listProto(stringProto("abc"), nullProto(), stringProto("bcd")), protoType: listType(stringType()), want: []CustomString{}, wantErr: true},
1409		{desc: "decode NULL to []CustomNullString", proto: nullProto(), protoType: listType(stringType()), want: []CustomNullString(nil)},
1410		{desc: "decode ARRAY<STRING> to []CustomNullString", proto: listProto(stringProto("abc"), nullProto(), stringProto("bcd")), protoType: listType(stringType()), want: []CustomNullString{{"abc", true}, {}, {"bcd", true}}},
1411		// BYTES ARRAY
1412		{desc: "decode NULL to []CustomBytes", proto: nullProto(), protoType: listType(bytesType()), want: []CustomBytes(nil)},
1413		{desc: "decode ARRAY<BYTES> to []CustomBytes", proto: listProto(bytesProto([]byte("abc")), nullProto(), bytesProto([]byte("bcd"))), protoType: listType(bytesType()), want: []CustomBytes{CustomBytes("abc"), CustomBytes(nil), CustomBytes("bcd")}},
1414		// INT64 ARRAY
1415		{desc: "decode NULL to []CustomInt64", proto: nullProto(), protoType: listType(intType()), want: []CustomInt64(nil)},
1416		{desc: "decode ARRAY<INT64> with NULL values to []CustomInt64", proto: listProto(intProto(-100), nullProto(), intProto(100)), protoType: listType(intType()), want: []CustomInt64{}, wantErr: true},
1417		{desc: "decode ARRAY<INT64> to []CustomInt64", proto: listProto(intProto(-100), intProto(100)), protoType: listType(intType()), want: []CustomInt64{-100, 100}},
1418		{desc: "decode NULL to []CustomNullInt64", proto: nullProto(), protoType: listType(intType()), want: []CustomNullInt64(nil)},
1419		{desc: "decode ARRAY<INT64> to []CustomNullInt64", proto: listProto(intProto(-100), nullProto(), intProto(100)), protoType: listType(intType()), want: []CustomNullInt64{{-100, true}, {}, {100, true}}},
1420		// BOOL ARRAY
1421		{desc: "decode NULL to []CustomBool", proto: nullProto(), protoType: listType(boolType()), want: []CustomBool(nil)},
1422		{desc: "decode ARRAY<BOOL> with NULL values to []CustomBool", proto: listProto(boolProto(false), nullProto(), boolProto(true)), protoType: listType(boolType()), want: []CustomBool{}, wantErr: true},
1423		{desc: "decode ARRAY<BOOL> to []CustomBool", proto: listProto(boolProto(false), boolProto(true)), protoType: listType(boolType()), want: []CustomBool{false, true}},
1424		{desc: "decode NULL to []CustomNullBool", proto: nullProto(), protoType: listType(boolType()), want: []CustomNullBool(nil)},
1425		{desc: "decode ARRAY<BOOL> to []CustomNullBool", proto: listProto(boolProto(false), nullProto(), boolProto(true)), protoType: listType(boolType()), want: []CustomNullBool{{false, true}, {}, {true, true}}},
1426		// FLOAT64 ARRAY
1427		{desc: "decode NULL to []CustomFloat64", proto: nullProto(), protoType: listType(floatType()), want: []CustomFloat64(nil)},
1428		{desc: "decode ARRAY<FLOAT64> with NULL values to []CustomFloat64", proto: listProto(floatProto(3.14), nullProto(), floatProto(6.626)), protoType: listType(floatType()), want: []CustomFloat64{}, wantErr: true},
1429		{desc: "decode ARRAY<FLOAT64> to []CustomFloat64", proto: listProto(floatProto(3.14), floatProto(6.626)), protoType: listType(floatType()), want: []CustomFloat64{3.14, 6.626}},
1430		{desc: "decode NULL to []CustomNullFloat64", proto: nullProto(), protoType: listType(floatType()), want: []CustomNullFloat64(nil)},
1431		{desc: "decode ARRAY<FLOAT64> to []CustomNullFloat64", proto: listProto(floatProto(3.14), nullProto(), floatProto(6.626)), protoType: listType(floatType()), want: []CustomNullFloat64{{3.14, true}, {}, {6.626, true}}},
1432		// TIME ARRAY
1433		{desc: "decode NULL to []CustomTime", proto: nullProto(), protoType: listType(timeType()), want: []CustomTime(nil)},
1434		{desc: "decode ARRAY<TIMESTAMP> with NULL values to []CustomTime", proto: listProto(timeProto(t1), nullProto(), timeProto(t2)), protoType: listType(timeType()), want: []CustomTime{}, wantErr: true},
1435		{desc: "decode ARRAY<TIMESTAMP> to []CustomTime", proto: listProto(timeProto(t1), timeProto(t2)), protoType: listType(timeType()), want: []CustomTime{CustomTime(t1), CustomTime(t2)}},
1436		{desc: "decode NULL to []CustomNullTime", proto: nullProto(), protoType: listType(timeType()), want: []CustomNullTime(nil)},
1437		{desc: "decode ARRAY<TIMESTAMP> to []CustomNullTime", proto: listProto(timeProto(t1), nullProto(), timeProto(t2)), protoType: listType(timeType()), want: []CustomNullTime{{t1, true}, {}, {t2, true}}},
1438		// DATE ARRAY
1439		{desc: "decode NULL to []CustomDate", proto: nullProto(), protoType: listType(dateType()), want: []CustomDate(nil)},
1440		{desc: "decode ARRAY<DATE> with NULL values to []CustomDate", proto: listProto(dateProto(d1), nullProto(), dateProto(d2)), protoType: listType(dateType()), want: []CustomDate{}, wantErr: true},
1441		{desc: "decode ARRAY<DATE> to []CustomDate", proto: listProto(dateProto(d1), dateProto(d2)), protoType: listType(dateType()), want: []CustomDate{CustomDate(d1), CustomDate(d2)}},
1442		{desc: "decode NULL to []CustomNullDate", proto: nullProto(), protoType: listType(dateType()), want: []CustomNullDate(nil)},
1443		{desc: "decode ARRAY<DATE> to []CustomNullDate", proto: listProto(dateProto(d1), nullProto(), dateProto(d2)), protoType: listType(dateType()), want: []CustomNullDate{{d1, true}, {}, {d2, true}}},
1444	} {
1445		gotp := reflect.New(reflect.TypeOf(test.want))
1446		err := decodeValue(test.proto, test.protoType, gotp.Interface())
1447		if test.wantErr {
1448			if err == nil {
1449				t.Errorf("%s: missing expected decode failure for %v(%v)", test.desc, test.proto, test.protoType)
1450			}
1451			continue
1452		}
1453		if err != nil {
1454			t.Errorf("%s: cannot decode %v(%v): %v", test.desc, test.proto, test.protoType, err)
1455			continue
1456		}
1457		got := reflect.Indirect(gotp).Interface()
1458		if !testutil.Equal(got, test.want, cmp.AllowUnexported(CustomTime{}, CustomDate{}, Row{})) {
1459			t.Errorf("%s: unexpected decoding result - got %v (%T), want %v (%T)", test.desc, got, got, test.want, test.want)
1460		}
1461	}
1462}
1463
1464// Test error cases for decodeValue.
1465func TestDecodeValueErrors(t *testing.T) {
1466	var s string
1467	for i, test := range []struct {
1468		in *proto3.Value
1469		t  *sppb.Type
1470		v  interface{}
1471	}{
1472		{nullProto(), stringType(), nil},
1473		{nullProto(), stringType(), 1},
1474		{timeProto(t1), timeType(), &s},
1475	} {
1476		err := decodeValue(test.in, test.t, test.v)
1477		if err == nil {
1478			t.Errorf("#%d: want error, got nil", i)
1479		}
1480	}
1481}
1482
1483func TestGetDecodableSpannerType(t *testing.T) {
1484	type CustomString string
1485	type CustomInt64 int64
1486	type CustomBool bool
1487	type CustomFloat64 float64
1488	type CustomTime time.Time
1489	type CustomDate civil.Date
1490
1491	type CustomNullString NullString
1492	type CustomNullInt64 NullInt64
1493	type CustomNullBool NullBool
1494	type CustomNullFloat64 NullFloat64
1495	type CustomNullTime NullTime
1496	type CustomNullDate NullDate
1497
1498	type StringEmbedded struct {
1499		string
1500	}
1501	type NullStringEmbedded struct {
1502		NullString
1503	}
1504
1505	for i, test := range []struct {
1506		in   interface{}
1507		want decodableSpannerType
1508	}{
1509		{"foo", spannerTypeNonNullString},
1510		{[]byte("ab"), spannerTypeByteArray},
1511		{[]byte(nil), spannerTypeByteArray},
1512		{int64(123), spannerTypeNonNullInt64},
1513		{true, spannerTypeNonNullBool},
1514		{3.14, spannerTypeNonNullFloat64},
1515		{time.Now(), spannerTypeNonNullTime},
1516		{civil.DateOf(time.Now()), spannerTypeNonNullDate},
1517		{NullString{}, spannerTypeNullString},
1518		{NullInt64{}, spannerTypeNullInt64},
1519		{NullBool{}, spannerTypeNullBool},
1520		{NullFloat64{}, spannerTypeNullFloat64},
1521		{NullTime{}, spannerTypeNullTime},
1522		{NullDate{}, spannerTypeNullDate},
1523
1524		{[]string{"foo", "bar"}, spannerTypeArrayOfNonNullString},
1525		{[][]byte{{1, 2, 3}, {3, 2, 1}}, spannerTypeArrayOfByteArray},
1526		{[][]byte{}, spannerTypeArrayOfByteArray},
1527		{[]int64{int64(123)}, spannerTypeArrayOfNonNullInt64},
1528		{[]bool{true}, spannerTypeArrayOfNonNullBool},
1529		{[]float64{3.14}, spannerTypeArrayOfNonNullFloat64},
1530		{[]time.Time{time.Now()}, spannerTypeArrayOfNonNullTime},
1531		{[]civil.Date{civil.DateOf(time.Now())}, spannerTypeArrayOfNonNullDate},
1532		{[]NullString{}, spannerTypeArrayOfNullString},
1533		{[]NullInt64{}, spannerTypeArrayOfNullInt64},
1534		{[]NullBool{}, spannerTypeArrayOfNullBool},
1535		{[]NullFloat64{}, spannerTypeArrayOfNullFloat64},
1536		{[]NullTime{}, spannerTypeArrayOfNullTime},
1537		{[]NullDate{}, spannerTypeArrayOfNullDate},
1538
1539		{CustomString("foo"), spannerTypeNonNullString},
1540		{CustomInt64(-100), spannerTypeNonNullInt64},
1541		{CustomBool(true), spannerTypeNonNullBool},
1542		{CustomFloat64(3.141592), spannerTypeNonNullFloat64},
1543		{CustomTime(time.Now()), spannerTypeNonNullTime},
1544		{CustomDate(civil.DateOf(time.Now())), spannerTypeNonNullDate},
1545
1546		{[]CustomString{}, spannerTypeArrayOfNonNullString},
1547		{[]CustomInt64{}, spannerTypeArrayOfNonNullInt64},
1548		{[]CustomBool{}, spannerTypeArrayOfNonNullBool},
1549		{[]CustomFloat64{}, spannerTypeArrayOfNonNullFloat64},
1550		{[]CustomTime{}, spannerTypeArrayOfNonNullTime},
1551		{[]CustomDate{}, spannerTypeArrayOfNonNullDate},
1552
1553		{CustomNullString{}, spannerTypeNullString},
1554		{CustomNullInt64{}, spannerTypeNullInt64},
1555		{CustomNullBool{}, spannerTypeNullBool},
1556		{CustomNullFloat64{}, spannerTypeNullFloat64},
1557		{CustomNullTime{}, spannerTypeNullTime},
1558		{CustomNullDate{}, spannerTypeNullDate},
1559
1560		{[]CustomNullString{}, spannerTypeArrayOfNullString},
1561		{[]CustomNullInt64{}, spannerTypeArrayOfNullInt64},
1562		{[]CustomNullBool{}, spannerTypeArrayOfNullBool},
1563		{[]CustomNullFloat64{}, spannerTypeArrayOfNullFloat64},
1564		{[]CustomNullTime{}, spannerTypeArrayOfNullTime},
1565		{[]CustomNullDate{}, spannerTypeArrayOfNullDate},
1566
1567		{StringEmbedded{}, spannerTypeUnknown},
1568		{NullStringEmbedded{}, spannerTypeUnknown},
1569	} {
1570		gotp := reflect.New(reflect.TypeOf(test.in))
1571		got := getDecodableSpannerType(gotp.Interface())
1572		if got != test.want {
1573			t.Errorf("%d: unexpected decodable type - got %v, want %v", i, got, test.want)
1574		}
1575	}
1576}
1577
1578// Test NaN encoding/decoding.
1579func TestNaN(t *testing.T) {
1580	// Decode NaN value.
1581	f := 0.0
1582	nf := NullFloat64{}
1583	// To float64
1584	if err := decodeValue(floatProto(math.NaN()), floatType(), &f); err != nil {
1585		t.Errorf("decodeValue returns %q for %v, want nil", err, floatProto(math.NaN()))
1586	}
1587	if !math.IsNaN(f) {
1588		t.Errorf("f = %v, want %v", f, math.NaN())
1589	}
1590	// To NullFloat64
1591	if err := decodeValue(floatProto(math.NaN()), floatType(), &nf); err != nil {
1592		t.Errorf("decodeValue returns %q for %v, want nil", err, floatProto(math.NaN()))
1593	}
1594	if !math.IsNaN(nf.Float64) || !nf.Valid {
1595		t.Errorf("f = %v, want %v", f, NullFloat64{math.NaN(), true})
1596	}
1597	// Encode NaN value
1598	// From float64
1599	v, _, err := encodeValue(math.NaN())
1600	if err != nil {
1601		t.Errorf("encodeValue returns %q for NaN, want nil", err)
1602	}
1603	x, ok := v.GetKind().(*proto3.Value_NumberValue)
1604	if !ok {
1605		t.Errorf("incorrect type for v.GetKind(): %T, want *proto3.Value_NumberValue", v.GetKind())
1606	}
1607	if !math.IsNaN(x.NumberValue) {
1608		t.Errorf("x.NumberValue = %v, want %v", x.NumberValue, math.NaN())
1609	}
1610	// From NullFloat64
1611	v, _, err = encodeValue(NullFloat64{math.NaN(), true})
1612	if err != nil {
1613		t.Errorf("encodeValue returns %q for NaN, want nil", err)
1614	}
1615	x, ok = v.GetKind().(*proto3.Value_NumberValue)
1616	if !ok {
1617		t.Errorf("incorrect type for v.GetKind(): %T, want *proto3.Value_NumberValue", v.GetKind())
1618	}
1619	if !math.IsNaN(x.NumberValue) {
1620		t.Errorf("x.NumberValue = %v, want %v", x.NumberValue, math.NaN())
1621	}
1622}
1623
1624func TestGenericColumnValue(t *testing.T) {
1625	for _, test := range []struct {
1626		in   GenericColumnValue
1627		want interface{}
1628		fail bool
1629	}{
1630		{GenericColumnValue{stringType(), stringProto("abc")}, "abc", false},
1631		{GenericColumnValue{stringType(), stringProto("abc")}, 5, true},
1632		{GenericColumnValue{listType(intType()), listProto(intProto(91), nullProto(), intProto(87))}, []NullInt64{{91, true}, {}, {87, true}}, false},
1633		{GenericColumnValue{intType(), intProto(42)}, GenericColumnValue{intType(), intProto(42)}, false}, // trippy! :-)
1634	} {
1635		gotp := reflect.New(reflect.TypeOf(test.want))
1636		if err := test.in.Decode(gotp.Interface()); err != nil {
1637			if !test.fail {
1638				t.Errorf("cannot decode %v to %v: %v", test.in, test.want, err)
1639			}
1640			continue
1641		}
1642		if test.fail {
1643			t.Errorf("decoding %v to %v succeeds unexpectedly", test.in, test.want)
1644		}
1645
1646		// Test we can go backwards as well.
1647		v, err := newGenericColumnValue(test.want)
1648		if err != nil {
1649			t.Errorf("NewGenericColumnValue failed: %v", err)
1650			continue
1651		}
1652		if !testEqual(*v, test.in) {
1653			t.Errorf("unexpected encode result - got %v, want %v", v, test.in)
1654		}
1655	}
1656}
1657
1658func TestDecodeStruct(t *testing.T) {
1659	type CustomString string
1660	type CustomTime time.Time
1661	stype := &sppb.StructType{Fields: []*sppb.StructType_Field{
1662		{Name: "Id", Type: stringType()},
1663		{Name: "Time", Type: timeType()},
1664	}}
1665	lv := listValueProto(stringProto("id"), timeProto(t1))
1666
1667	type (
1668		S1 struct {
1669			ID   string
1670			Time time.Time
1671		}
1672		S2 struct {
1673			ID   string
1674			Time string
1675		}
1676		S3 struct {
1677			ID   CustomString
1678			Time CustomTime
1679		}
1680		S4 struct {
1681			ID   CustomString
1682			Time CustomString
1683		}
1684		S5 struct {
1685			NullString
1686			Time CustomTime
1687		}
1688	)
1689	var (
1690		s1 S1
1691		s2 S2
1692		s3 S3
1693		s4 S4
1694		s5 S5
1695	)
1696
1697	for _, test := range []struct {
1698		desc string
1699		ptr  interface{}
1700		want interface{}
1701		fail bool
1702	}{
1703		{
1704			desc: "decode to S1",
1705			ptr:  &s1,
1706			want: &S1{ID: "id", Time: t1},
1707		},
1708		{
1709			desc: "decode to S2",
1710			ptr:  &s2,
1711			fail: true,
1712		},
1713		{
1714			desc: "decode to S3",
1715			ptr:  &s3,
1716			want: &S3{ID: CustomString("id"), Time: CustomTime(t1)},
1717		},
1718		{
1719			desc: "decode to S4",
1720			ptr:  &s4,
1721			fail: true,
1722		},
1723		{
1724			desc: "decode to S5",
1725			ptr:  &s5,
1726			fail: true,
1727		},
1728	} {
1729		err := decodeStruct(stype, lv, test.ptr)
1730		if (err != nil) != test.fail {
1731			t.Errorf("%s: got error %v, wanted fail: %v", test.desc, err, test.fail)
1732		}
1733		if err == nil {
1734			if !testutil.Equal(test.ptr, test.want, cmp.AllowUnexported(CustomTime{})) {
1735				t.Errorf("%s: got %+v, want %+v", test.desc, test.ptr, test.want)
1736			}
1737		}
1738	}
1739}
1740
1741func TestDecodeStructWithPointers(t *testing.T) {
1742	stype := &sppb.StructType{Fields: []*sppb.StructType_Field{
1743		{Name: "Str", Type: stringType()},
1744		{Name: "Int", Type: intType()},
1745		{Name: "Bool", Type: boolType()},
1746		{Name: "Float", Type: floatType()},
1747		{Name: "Time", Type: timeType()},
1748		{Name: "Date", Type: dateType()},
1749		{Name: "StrArray", Type: listType(stringType())},
1750		{Name: "IntArray", Type: listType(intType())},
1751		{Name: "BoolArray", Type: listType(boolType())},
1752		{Name: "FloatArray", Type: listType(floatType())},
1753		{Name: "TimeArray", Type: listType(timeType())},
1754		{Name: "DateArray", Type: listType(dateType())},
1755	}}
1756	lv := []*proto3.ListValue{
1757		listValueProto(
1758			stringProto("id"),
1759			intProto(15),
1760			boolProto(true),
1761			floatProto(3.14),
1762			timeProto(t1),
1763			dateProto(d1),
1764			listProto(stringProto("id1"), nullProto(), stringProto("id2")),
1765			listProto(intProto(16), nullProto(), intProto(17)),
1766			listProto(boolProto(true), nullProto(), boolProto(false)),
1767			listProto(floatProto(3.14), nullProto(), floatProto(6.626)),
1768			listProto(timeProto(t1), nullProto(), timeProto(t2)),
1769			listProto(dateProto(d1), nullProto(), dateProto(d2)),
1770		),
1771		listValueProto(
1772			nullProto(),
1773			nullProto(),
1774			nullProto(),
1775			nullProto(),
1776			nullProto(),
1777			nullProto(),
1778			nullProto(),
1779			nullProto(),
1780			nullProto(),
1781			nullProto(),
1782			nullProto(),
1783			nullProto(),
1784		),
1785	}
1786
1787	type S1 struct {
1788		Str        *string
1789		Int        *int64
1790		Bool       *bool
1791		Float      *float64
1792		Time       *time.Time
1793		Date       *civil.Date
1794		StrArray   []*string
1795		IntArray   []*int64
1796		BoolArray  []*bool
1797		FloatArray []*float64
1798		TimeArray  []*time.Time
1799		DateArray  []*civil.Date
1800	}
1801	var s1 S1
1802	sValue := "id"
1803	iValue := int64(15)
1804	bValue := true
1805	fValue := 3.14
1806	tValue := t1
1807	dValue := d1
1808	sArrayValue1 := "id1"
1809	sArrayValue2 := "id2"
1810	sArrayValue := []*string{&sArrayValue1, nil, &sArrayValue2}
1811	iArrayValue1 := int64(16)
1812	iArrayValue2 := int64(17)
1813	iArrayValue := []*int64{&iArrayValue1, nil, &iArrayValue2}
1814	bArrayValue1 := true
1815	bArrayValue2 := false
1816	bArrayValue := []*bool{&bArrayValue1, nil, &bArrayValue2}
1817	f1Value := 3.14
1818	f2Value := 6.626
1819	fArrayValue := []*float64{&f1Value, nil, &f2Value}
1820	t1Value := t1
1821	t2Value := t2
1822	tArrayValue := []*time.Time{&t1Value, nil, &t2Value}
1823	d1Value := d1
1824	d2Value := d2
1825	dArrayValue := []*civil.Date{&d1Value, nil, &d2Value}
1826
1827	for i, test := range []struct {
1828		desc string
1829		ptr  *S1
1830		want *S1
1831		fail bool
1832	}{
1833		{
1834			desc: "decode values to S1",
1835			ptr:  &s1,
1836			want: &S1{Str: &sValue, Int: &iValue, Bool: &bValue, Float: &fValue, Time: &tValue, Date: &dValue, StrArray: sArrayValue, IntArray: iArrayValue, BoolArray: bArrayValue, FloatArray: fArrayValue, TimeArray: tArrayValue, DateArray: dArrayValue},
1837		},
1838		{
1839			desc: "decode nulls to S1",
1840			ptr:  &s1,
1841			want: &S1{Str: nil, Int: nil, Bool: nil, Float: nil, Time: nil, Date: nil, StrArray: nil, IntArray: nil, BoolArray: nil, FloatArray: nil, TimeArray: nil, DateArray: nil},
1842		},
1843	} {
1844		err := decodeStruct(stype, lv[i], test.ptr)
1845		if (err != nil) != test.fail {
1846			t.Errorf("%s: got error %v, wanted fail: %v", test.desc, err, test.fail)
1847		}
1848		if err == nil {
1849			if !testutil.Equal(test.ptr, test.want) {
1850				t.Errorf("%s: got %+v, want %+v", test.desc, test.ptr, test.want)
1851			}
1852		}
1853	}
1854}
1855
1856func TestEncodeStructValueDynamicStructs(t *testing.T) {
1857	dynStructType := reflect.StructOf([]reflect.StructField{
1858		{Name: "A", Type: reflect.TypeOf(0), Tag: `spanner:"a"`},
1859		{Name: "B", Type: reflect.TypeOf(""), Tag: `spanner:"b"`},
1860	})
1861	dynNullableStructType := reflect.PtrTo(dynStructType)
1862	dynStructArrType := reflect.SliceOf(dynStructType)
1863	dynNullableStructArrType := reflect.SliceOf(dynNullableStructType)
1864
1865	dynStructValue := reflect.New(dynStructType)
1866	dynStructValue.Elem().Field(0).SetInt(10)
1867	dynStructValue.Elem().Field(1).SetString("abc")
1868
1869	dynStructArrValue := reflect.MakeSlice(dynNullableStructArrType, 2, 2)
1870	dynStructArrValue.Index(0).Set(reflect.Zero(dynNullableStructType))
1871	dynStructArrValue.Index(1).Set(dynStructValue)
1872
1873	structProtoType := structType(
1874		mkField("a", intType()),
1875		mkField("b", stringType()))
1876
1877	arrProtoType := listType(structProtoType)
1878
1879	for _, test := range []encodeTest{
1880		{
1881			"Dynanic non-NULL struct value.",
1882			dynStructValue.Elem().Interface(),
1883			listProto(intProto(10), stringProto("abc")),
1884			structProtoType,
1885		},
1886		{
1887			"Dynanic NULL struct value.",
1888			reflect.Zero(dynNullableStructType).Interface(),
1889			nullProto(),
1890			structProtoType,
1891		},
1892		{
1893			"Empty array of dynamic structs.",
1894			reflect.MakeSlice(dynStructArrType, 0, 0).Interface(),
1895			listProto([]*proto3.Value{}...),
1896			arrProtoType,
1897		},
1898		{
1899			"NULL array of non-NULL-able dynamic structs.",
1900			reflect.Zero(dynStructArrType).Interface(),
1901			nullProto(),
1902			arrProtoType,
1903		},
1904		{
1905			"NULL array of NULL-able(nil) dynamic structs.",
1906			reflect.Zero(dynNullableStructArrType).Interface(),
1907			nullProto(),
1908			arrProtoType,
1909		},
1910		{
1911			"Array containing NULL(nil) dynamic-typed struct elements.",
1912			dynStructArrValue.Interface(),
1913			listProto(
1914				nullProto(),
1915				listProto(intProto(10), stringProto("abc"))),
1916			arrProtoType,
1917		},
1918	} {
1919		encodeStructValue(test, t)
1920	}
1921}
1922
1923func TestEncodeStructValueEmptyStruct(t *testing.T) {
1924	emptyListValue := listProto([]*proto3.Value{}...)
1925	emptyStructType := structType([]*sppb.StructType_Field{}...)
1926	emptyStruct := struct{}{}
1927	nullEmptyStruct := (*struct{})(nil)
1928
1929	dynamicEmptyStructType := reflect.StructOf(make([]reflect.StructField, 0, 0))
1930	dynamicStructArrType := reflect.SliceOf(reflect.PtrTo((dynamicEmptyStructType)))
1931
1932	dynamicEmptyStruct := reflect.New(dynamicEmptyStructType)
1933	dynamicNullEmptyStruct := reflect.Zero(reflect.PtrTo(dynamicEmptyStructType))
1934
1935	dynamicStructArrValue := reflect.MakeSlice(dynamicStructArrType, 2, 2)
1936	dynamicStructArrValue.Index(0).Set(dynamicNullEmptyStruct)
1937	dynamicStructArrValue.Index(1).Set(dynamicEmptyStruct)
1938
1939	for _, test := range []encodeTest{
1940		{
1941			"Go empty struct.",
1942			emptyStruct,
1943			emptyListValue,
1944			emptyStructType,
1945		},
1946		{
1947			"Dynamic empty struct.",
1948			dynamicEmptyStruct.Interface(),
1949			emptyListValue,
1950			emptyStructType,
1951		},
1952		{
1953			"Go NULL empty struct.",
1954			nullEmptyStruct,
1955			nullProto(),
1956			emptyStructType,
1957		},
1958		{
1959			"Dynamic NULL empty struct.",
1960			dynamicNullEmptyStruct.Interface(),
1961			nullProto(),
1962			emptyStructType,
1963		},
1964		{
1965			"Non-empty array of dynamic NULL and non-NULL empty structs.",
1966			dynamicStructArrValue.Interface(),
1967			listProto(nullProto(), emptyListValue),
1968			listType(emptyStructType),
1969		},
1970		{
1971			"Non-empty array of nullable empty structs.",
1972			[]*struct{}{nullEmptyStruct, &emptyStruct},
1973			listProto(nullProto(), emptyListValue),
1974			listType(emptyStructType),
1975		},
1976		{
1977			"Empty array of empty struct.",
1978			[]struct{}{},
1979			emptyListValue,
1980			listType(emptyStructType),
1981		},
1982		{
1983			"Null array of empty structs.",
1984			[]struct{}(nil),
1985			nullProto(),
1986			listType(emptyStructType),
1987		},
1988	} {
1989		encodeStructValue(test, t)
1990	}
1991}
1992
1993func TestEncodeStructValueMixedStructTypes(t *testing.T) {
1994	type staticStruct struct {
1995		F int `spanner:"fStatic"`
1996	}
1997	s1 := staticStruct{10}
1998	s2 := (*staticStruct)(nil)
1999
2000	var f float64
2001	dynStructType := reflect.StructOf([]reflect.StructField{
2002		{Name: "A", Type: reflect.TypeOf(f), Tag: `spanner:"fDynamic"`},
2003	})
2004	s3 := reflect.New(dynStructType)
2005	s3.Elem().Field(0).SetFloat(3.14)
2006
2007	for _, test := range []encodeTest{
2008		{
2009			"'struct' with static and dynamic *struct, []*struct, []struct fields",
2010			struct {
2011				A []staticStruct
2012				B []*staticStruct
2013				C interface{}
2014			}{
2015				[]staticStruct{s1, s1},
2016				[]*staticStruct{&s1, s2},
2017				s3.Interface(),
2018			},
2019			listProto(
2020				listProto(listProto(intProto(10)), listProto(intProto(10))),
2021				listProto(listProto(intProto(10)), nullProto()),
2022				listProto(floatProto(3.14))),
2023			structType(
2024				mkField("A", listType(structType(mkField("fStatic", intType())))),
2025				mkField("B", listType(structType(mkField("fStatic", intType())))),
2026				mkField("C", structType(mkField("fDynamic", floatType())))),
2027		},
2028	} {
2029		encodeStructValue(test, t)
2030	}
2031}
2032
2033func TestBindParamsDynamic(t *testing.T) {
2034	// Verify Statement.bindParams generates correct values and types.
2035	st := Statement{
2036		SQL:    "SELECT id from t_foo WHERE col = @var",
2037		Params: map[string]interface{}{"var": nil},
2038	}
2039	want := &sppb.ExecuteSqlRequest{
2040		Params: &proto3.Struct{
2041			Fields: map[string]*proto3.Value{"var": nil},
2042		},
2043		ParamTypes: map[string]*sppb.Type{"var": nil},
2044	}
2045	var (
2046		t1, _ = time.Parse(time.RFC3339Nano, "2016-11-15T15:04:05.999999999Z")
2047		// Boundaries
2048		t2, _ = time.Parse(time.RFC3339Nano, "0001-01-01T00:00:00.000000000Z")
2049	)
2050	dynamicStructType := reflect.StructOf([]reflect.StructField{
2051		{Name: "A", Type: reflect.TypeOf(t1), Tag: `spanner:"field"`},
2052		{Name: "B", Type: reflect.TypeOf(3.14), Tag: `spanner:""`},
2053	})
2054	dynamicStructArrType := reflect.SliceOf(reflect.PtrTo(dynamicStructType))
2055	dynamicEmptyStructType := reflect.StructOf(make([]reflect.StructField, 0, 0))
2056
2057	dynamicStructTypeProto := structType(
2058		mkField("field", timeType()),
2059		mkField("", floatType()))
2060
2061	s3 := reflect.New(dynamicStructType)
2062	s3.Elem().Field(0).Set(reflect.ValueOf(t1))
2063	s3.Elem().Field(1).SetFloat(1.4)
2064
2065	s4 := reflect.New(dynamicStructType)
2066	s4.Elem().Field(0).Set(reflect.ValueOf(t2))
2067	s4.Elem().Field(1).SetFloat(-13.3)
2068
2069	dynamicStructArrayVal := reflect.MakeSlice(dynamicStructArrType, 2, 2)
2070	dynamicStructArrayVal.Index(0).Set(s3)
2071	dynamicStructArrayVal.Index(1).Set(s4)
2072
2073	for _, test := range []struct {
2074		val       interface{}
2075		wantField *proto3.Value
2076		wantType  *sppb.Type
2077	}{
2078		{
2079			s3.Interface(),
2080			listProto(timeProto(t1), floatProto(1.4)),
2081			structType(
2082				mkField("field", timeType()),
2083				mkField("", floatType())),
2084		},
2085		{
2086			reflect.Zero(reflect.PtrTo(dynamicEmptyStructType)).Interface(),
2087			nullProto(),
2088			structType([]*sppb.StructType_Field{}...),
2089		},
2090		{
2091			dynamicStructArrayVal.Interface(),
2092			listProto(
2093				listProto(timeProto(t1), floatProto(1.4)),
2094				listProto(timeProto(t2), floatProto(-13.3))),
2095			listType(dynamicStructTypeProto),
2096		},
2097		{
2098			[]*struct {
2099				F1 time.Time `spanner:"field"`
2100				F2 float64   `spanner:""`
2101			}{
2102				nil,
2103				{t1, 1.4},
2104			},
2105			listProto(
2106				nullProto(),
2107				listProto(timeProto(t1), floatProto(1.4))),
2108			listType(dynamicStructTypeProto),
2109		},
2110	} {
2111		st.Params["var"] = test.val
2112		want.Params.Fields["var"] = test.wantField
2113		want.ParamTypes["var"] = test.wantType
2114		gotParams, gotParamTypes, gotErr := st.convertParams()
2115		if gotErr != nil {
2116			t.Error(gotErr)
2117			continue
2118		}
2119		gotParamField := gotParams.Fields["var"]
2120		if !proto.Equal(gotParamField, test.wantField) {
2121			// handle NaN
2122			if test.wantType.Code == floatType().Code && proto.MarshalTextString(gotParamField) == proto.MarshalTextString(test.wantField) {
2123				continue
2124			}
2125			t.Errorf("%#v: got %v, want %v\n", test.val, gotParamField, test.wantField)
2126		}
2127		gotParamType := gotParamTypes["var"]
2128		if !proto.Equal(gotParamType, test.wantType) {
2129			t.Errorf("%#v: got %v, want %v\n", test.val, gotParamType, test.wantField)
2130		}
2131	}
2132}
2133
2134// Test converting nullable types to json strings.
2135func TestJSONMarshal_NullTypes(t *testing.T) {
2136	type testcase struct {
2137		input  interface{}
2138		expect string
2139	}
2140
2141	for _, test := range []struct {
2142		name  string
2143		cases []testcase
2144	}{
2145		{
2146			"NullString",
2147			[]testcase{
2148				{input: NullString{"this is a test string", true}, expect: `"this is a test string"`},
2149				{input: &NullString{"this is a test string", true}, expect: `"this is a test string"`},
2150				{input: &NullString{"this is a test string", false}, expect: "null"},
2151				{input: NullString{}, expect: "null"},
2152			},
2153		},
2154		{
2155			"NullInt64",
2156			[]testcase{
2157				{input: NullInt64{int64(123), true}, expect: "123"},
2158				{input: &NullInt64{int64(123), true}, expect: "123"},
2159				{input: &NullInt64{int64(123), false}, expect: "null"},
2160				{input: NullInt64{}, expect: "null"},
2161			},
2162		},
2163		{
2164			"NullFloat64",
2165			[]testcase{
2166				{input: NullFloat64{float64(123.123), true}, expect: "123.123"},
2167				{input: &NullFloat64{float64(123.123), true}, expect: "123.123"},
2168				{input: &NullFloat64{float64(123.123), false}, expect: "null"},
2169				{input: NullFloat64{}, expect: "null"},
2170			},
2171		},
2172		{
2173			"NullBool",
2174			[]testcase{
2175				{input: NullBool{true, true}, expect: "true"},
2176				{input: &NullBool{true, true}, expect: "true"},
2177				{input: &NullBool{true, false}, expect: "null"},
2178				{input: NullBool{}, expect: "null"},
2179			},
2180		},
2181		{
2182			"NullTime",
2183			[]testcase{
2184				{input: NullTime{time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC), true}, expect: `"2009-11-17T20:34:58.651387237Z"`},
2185				{input: &NullTime{time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC), true}, expect: `"2009-11-17T20:34:58.651387237Z"`},
2186				{input: &NullTime{time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC), false}, expect: "null"},
2187				{input: NullTime{}, expect: "null"},
2188			},
2189		},
2190		{
2191			"NullDate",
2192			[]testcase{
2193				{input: NullDate{civil.Date{Year: 2009, Month: time.November, Day: 17}, true}, expect: `"2009-11-17"`},
2194				{input: &NullDate{civil.Date{Year: 2009, Month: time.November, Day: 17}, true}, expect: `"2009-11-17"`},
2195				{input: &NullDate{civil.Date{Year: 2009, Month: time.November, Day: 17}, false}, expect: "null"},
2196				{input: NullDate{}, expect: "null"},
2197			},
2198		},
2199	} {
2200		t.Run(test.name, func(t *testing.T) {
2201			for _, tc := range test.cases {
2202				bytes, _ := json.Marshal(tc.input)
2203				got := string(bytes)
2204				if got != tc.expect {
2205					t.Fatalf("Incorrect marshalling to json strings: got %v, want %v", got, tc.expect)
2206				}
2207			}
2208		})
2209	}
2210}
2211
2212// Test converting json strings to nullable types.
2213func TestJSONUnmarshal_NullTypes(t *testing.T) {
2214	type testcase struct {
2215		input       []byte
2216		got         interface{}
2217		isNull      bool
2218		expect      string
2219		expectError bool
2220	}
2221
2222	for _, test := range []struct {
2223		name  string
2224		cases []testcase
2225	}{
2226		{
2227			"NullString",
2228			[]testcase{
2229				{input: []byte(`"this is a test string"`), got: NullString{}, isNull: false, expect: "this is a test string", expectError: false},
2230				{input: []byte(`""`), got: NullString{}, isNull: false, expect: "", expectError: false},
2231				{input: []byte("null"), got: NullString{}, isNull: true, expect: nullString, expectError: false},
2232				{input: nil, got: NullString{}, isNull: true, expect: nullString, expectError: true},
2233				{input: []byte(""), got: NullString{}, isNull: true, expect: nullString, expectError: true},
2234				{input: []byte(`"hello`), got: NullString{}, isNull: true, expect: nullString, expectError: true},
2235			},
2236		},
2237		{
2238			"NullInt64",
2239			[]testcase{
2240				{input: []byte("123"), got: NullInt64{}, isNull: false, expect: "123", expectError: false},
2241				{input: []byte("null"), got: NullInt64{}, isNull: true, expect: nullString, expectError: false},
2242				{input: nil, got: NullInt64{}, isNull: true, expect: nullString, expectError: true},
2243				{input: []byte(""), got: NullInt64{}, isNull: true, expect: nullString, expectError: true},
2244				{input: []byte(`"hello`), got: NullInt64{}, isNull: true, expect: nullString, expectError: true},
2245			},
2246		},
2247		{
2248			"NullFloat64",
2249			[]testcase{
2250				{input: []byte("123.123"), got: NullFloat64{}, isNull: false, expect: "123.123", expectError: false},
2251				{input: []byte("null"), got: NullFloat64{}, isNull: true, expect: nullString, expectError: false},
2252				{input: nil, got: NullFloat64{}, isNull: true, expect: nullString, expectError: true},
2253				{input: []byte(""), got: NullFloat64{}, isNull: true, expect: nullString, expectError: true},
2254				{input: []byte(`"hello`), got: NullFloat64{}, isNull: true, expect: nullString, expectError: true},
2255			},
2256		},
2257		{
2258			"NullBool",
2259			[]testcase{
2260				{input: []byte("true"), got: NullBool{}, isNull: false, expect: "true", expectError: false},
2261				{input: []byte("null"), got: NullBool{}, isNull: true, expect: nullString, expectError: false},
2262				{input: nil, got: NullBool{}, isNull: true, expect: nullString, expectError: true},
2263				{input: []byte(""), got: NullBool{}, isNull: true, expect: nullString, expectError: true},
2264				{input: []byte(`"hello`), got: NullBool{}, isNull: true, expect: nullString, expectError: true},
2265			},
2266		},
2267		{
2268			"NullTime",
2269			[]testcase{
2270				{input: []byte(`"2009-11-17T20:34:58.651387237Z"`), got: NullTime{}, isNull: false, expect: "2009-11-17T20:34:58.651387237Z", expectError: false},
2271				{input: []byte("null"), got: NullTime{}, isNull: true, expect: nullString, expectError: false},
2272				{input: nil, got: NullTime{}, isNull: true, expect: nullString, expectError: true},
2273				{input: []byte(""), got: NullTime{}, isNull: true, expect: nullString, expectError: true},
2274				{input: []byte(`"hello`), got: NullTime{}, isNull: true, expect: nullString, expectError: true},
2275			},
2276		},
2277		{
2278			"NullDate",
2279			[]testcase{
2280				{input: []byte(`"2009-11-17"`), got: NullDate{}, isNull: false, expect: "2009-11-17", expectError: false},
2281				{input: []byte("null"), got: NullDate{}, isNull: true, expect: nullString, expectError: false},
2282				{input: nil, got: NullDate{}, isNull: true, expect: nullString, expectError: true},
2283				{input: []byte(""), got: NullDate{}, isNull: true, expect: nullString, expectError: true},
2284				{input: []byte(`"hello`), got: NullDate{}, isNull: true, expect: nullString, expectError: true},
2285			},
2286		},
2287	} {
2288		t.Run(test.name, func(t *testing.T) {
2289			for _, tc := range test.cases {
2290				switch v := tc.got.(type) {
2291				case NullString:
2292					err := json.Unmarshal(tc.input, &v)
2293					expectUnmarshalNullableTypes(t, err, v, tc.isNull, tc.expect, tc.expectError)
2294				case NullInt64:
2295					err := json.Unmarshal(tc.input, &v)
2296					expectUnmarshalNullableTypes(t, err, v, tc.isNull, tc.expect, tc.expectError)
2297				case NullFloat64:
2298					err := json.Unmarshal(tc.input, &v)
2299					expectUnmarshalNullableTypes(t, err, v, tc.isNull, tc.expect, tc.expectError)
2300				case NullBool:
2301					err := json.Unmarshal(tc.input, &v)
2302					expectUnmarshalNullableTypes(t, err, v, tc.isNull, tc.expect, tc.expectError)
2303				case NullTime:
2304					err := json.Unmarshal(tc.input, &v)
2305					expectUnmarshalNullableTypes(t, err, v, tc.isNull, tc.expect, tc.expectError)
2306				case NullDate:
2307					err := json.Unmarshal(tc.input, &v)
2308					expectUnmarshalNullableTypes(t, err, v, tc.isNull, tc.expect, tc.expectError)
2309				default:
2310					t.Fatalf("Unknown type: %T", v)
2311				}
2312			}
2313		})
2314	}
2315}
2316
2317func expectUnmarshalNullableTypes(t *testing.T, err error, v interface{}, isNull bool, expect string, expectError bool) {
2318	if expectError {
2319		if err == nil {
2320			t.Fatalf("Expect to get an error, but got a nil")
2321		}
2322		return
2323	}
2324
2325	if err != nil {
2326		t.Fatalf("Got an error when unmarshalling a valid json string: %q", err)
2327	}
2328	if s, ok := v.(NullableValue); !ok || s.IsNull() != isNull {
2329		t.Fatalf("Incorrect unmarshalling a json string to nullable types: got %q, want %q", v, expect)
2330	}
2331	if s, ok := v.(fmt.Stringer); !ok || s.String() != expect {
2332		t.Fatalf("Incorrect unmarshalling a json string to nullable types: got %q, want %q", v, expect)
2333	}
2334}
2335