Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(spanner): enable more tests on emulator #5442

Merged
merged 6 commits into from
Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion spanner/emulator_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export GCLOUD_TESTS_GOLANG_PROJECT_ID=emulator-test-project
echo "Running the Cloud Spanner emulator: $SPANNER_EMULATOR_HOST";

# Download the emulator
EMULATOR_VERSION=1.2.0
# TODO: Find a way to use 'latest' here.
EMULATOR_VERSION=1.4.0
olavloite marked this conversation as resolved.
Show resolved Hide resolved
wget https://storage.googleapis.com/cloud-spanner-emulator/releases/${EMULATOR_VERSION}/cloud-spanner-emulator_linux_amd64-${EMULATOR_VERSION}.tar.gz
tar zxvf cloud-spanner-emulator_linux_amd64-${EMULATOR_VERSION}.tar.gz
chmod u+x emulator_main
Expand Down
113 changes: 50 additions & 63 deletions spanner/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1569,23 +1569,21 @@ func TestIntegration_BasicTypes(t *testing.T) {

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
stmts := singerDBStatements
olavloite marked this conversation as resolved.
Show resolved Hide resolved
if !isEmulatorEnvSet() {
stmts = []string{
`CREATE TABLE Singers (
stmts := []string{
`CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX)
) PRIMARY KEY (SingerId)`,
`CREATE INDEX SingerByName ON Singers(FirstName, LastName)`,
`CREATE TABLE Accounts (
`CREATE INDEX SingerByName ON Singers(FirstName, LastName)`,
`CREATE TABLE Accounts (
AccountId INT64 NOT NULL,
Nickname STRING(100),
Balance INT64 NOT NULL,
) PRIMARY KEY (AccountId)`,
`CREATE INDEX AccountByNickname ON Accounts(Nickname) STORING (Balance)`,
`CREATE TABLE Types (
`CREATE INDEX AccountByNickname ON Accounts(Nickname) STORING (Balance)`,
`CREATE TABLE Types (
RowID INT64 NOT NULL,
String STRING(MAX),
StringArray ARRAY<STRING(MAX)>,
Expand All @@ -1606,7 +1604,6 @@ func TestIntegration_BasicTypes(t *testing.T) {
JSON JSON,
JSONArray ARRAY<JSON>
) PRIMARY KEY (RowID)`,
}
}
client, _, cleanup := prepareIntegrationTest(ctx, t, DefaultSessionPoolConfig, stmts)
defer cleanup()
Expand Down Expand Up @@ -1647,7 +1644,6 @@ func TestIntegration_BasicTypes(t *testing.T) {
{col: "String", val: "foo", want: NullString{"foo", true}},
{col: "String", val: NullString{"bar", true}, want: "bar"},
{col: "String", val: NullString{"bar", false}, want: NullString{"", false}},
{col: "String", val: nil, want: NullString{}},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed as it was a duplicate (the same test is on line 1737). This also applies to a couple of other tests below.

{col: "StringArray", val: []string(nil), want: []NullString(nil)},
{col: "StringArray", val: []string{}, want: []NullString{}},
{col: "StringArray", val: []string{"foo", "bar"}, want: []NullString{{"foo", true}, {"bar", true}}},
Expand All @@ -1668,7 +1664,6 @@ func TestIntegration_BasicTypes(t *testing.T) {
{col: "Int64a", val: NullInt64{5, true}, want: int64(5)},
{col: "Int64a", val: NullInt64{6, true}, want: int64(6)},
{col: "Int64a", val: NullInt64{7, false}, want: NullInt64{0, false}},
{col: "Int64a", val: nil, want: NullInt64{}},
{col: "Int64Array", val: []int(nil), want: []NullInt64(nil)},
{col: "Int64Array", val: []int{}, want: []NullInt64{}},
{col: "Int64Array", val: []int{1, 2}, want: []NullInt64{{1, true}, {2, true}}},
Expand All @@ -1684,7 +1679,6 @@ func TestIntegration_BasicTypes(t *testing.T) {
{col: "Bool", val: true, want: NullBool{true, true}},
{col: "Bool", val: NullBool{true, true}},
{col: "Bool", val: NullBool{false, false}},
{col: "Bool", val: nil, want: NullBool{}},
{col: "BoolArray", val: []bool(nil), want: []NullBool(nil)},
{col: "BoolArray", val: []bool{}, want: []NullBool{}},
{col: "BoolArray", val: []bool{true, false}, want: []NullBool{{true, true}, {false, true}}},
Expand All @@ -1700,7 +1694,6 @@ func TestIntegration_BasicTypes(t *testing.T) {
{col: "Float64", val: NullFloat64{2.71, true}, want: 2.71},
{col: "Float64", val: NullFloat64{1.41, true}, want: NullFloat64{1.41, true}},
{col: "Float64", val: NullFloat64{0, false}},
{col: "Float64", val: nil, want: NullFloat64{}},
{col: "Float64Array", val: []float64(nil), want: []NullFloat64(nil)},
{col: "Float64Array", val: []float64{}, want: []NullFloat64{}},
{col: "Float64Array", val: []float64{2.72, 3.14, math.Inf(1)}, want: []NullFloat64{{2.72, true}, {3.14, true}, {math.Inf(1), true}}},
Expand All @@ -1720,7 +1713,6 @@ func TestIntegration_BasicTypes(t *testing.T) {
{col: "Timestamp", val: NullTime{t1, true}},
{col: "Timestamp", val: NullTime{t1, true}, want: t1},
{col: "Timestamp", val: NullTime{}},
{col: "Timestamp", val: nil, want: NullTime{}},
{col: "TimestampArray", val: []time.Time(nil), want: []NullTime(nil)},
{col: "TimestampArray", val: []time.Time{}, want: []NullTime{}},
{col: "TimestampArray", val: []time.Time{t1, t2, t3}, want: []NullTime{{t1, true}, {t2, true}, {t3, true}}},
Expand All @@ -1731,13 +1723,17 @@ func TestIntegration_BasicTypes(t *testing.T) {
{col: "Numeric", val: NullNumeric{n1, true}, want: n1},
{col: "Numeric", val: NullNumeric{n1, true}, want: NullNumeric{n1, true}},
{col: "Numeric", val: NullNumeric{n0, false}},
{col: "Numeric", val: nil, want: NullNumeric{}},
{col: "NumericArray", val: []big.Rat(nil), want: []NullNumeric(nil)},
{col: "NumericArray", val: []big.Rat{}, want: []NullNumeric{}},
{col: "NumericArray", val: []big.Rat{n1, n2}, want: []NullNumeric{{n1, true}, {n2, true}}},
{col: "NumericArray", val: []NullNumeric(nil)},
{col: "NumericArray", val: []NullNumeric{}},
{col: "NumericArray", val: []NullNumeric{{n1, true}, {n2, true}, {}}},
{col: "JSON", val: NullJSON{msg, true}, want: NullJSON{unmarshalledJSONstruct, true}},
{col: "JSON", val: NullJSON{msg, false}, want: NullJSON{}},
{col: "JSONArray", val: []NullJSON(nil)},
{col: "JSONArray", val: []NullJSON{}},
{col: "JSONArray", val: []NullJSON{{msg, true}, {msg, true}, {}}, want: []NullJSON{{unmarshalledJSONstruct, true}, {unmarshalledJSONstruct, true}, {}}},
{col: "String", val: nil, want: NullString{}},
{col: "StringArray", val: nil, want: []NullString(nil)},
{col: "Bytes", val: nil, want: []byte(nil)},
Expand All @@ -1748,67 +1744,58 @@ func TestIntegration_BasicTypes(t *testing.T) {
{col: "BoolArray", val: nil, want: []NullBool(nil)},
{col: "Float64", val: nil, want: NullFloat64{}},
{col: "Float64Array", val: nil, want: []NullFloat64(nil)},
{col: "Date", val: nil, want: NullDate{}},
{col: "DateArray", val: nil, want: []NullDate(nil)},
{col: "Timestamp", val: nil, want: NullTime{}},
{col: "TimestampArray", val: nil, want: []NullTime(nil)},
{col: "Numeric", val: nil, want: NullNumeric{}},
{col: "NumericArray", val: nil, want: []NullNumeric(nil)},
{col: "JSON", val: nil, want: NullJSON{}},
{col: "JSONArray", val: nil, want: []NullJSON(nil)},
}

// Write rows into table first using DML. Only do this on real Spanner
// as the emulator does not support untyped parameters.
// TODO: Remove when the emulator supports untyped parameters.
if !isEmulatorEnvSet() {
statements := make([]Statement, 0)
for i, test := range tests {
stmt := NewStatement(fmt.Sprintf("INSERT INTO Types (RowId, `%s`) VALUES (@id, @value)", test.col))
// Note: We are not setting the parameter type here to ensure that it
// can be automatically recognized when it is actually needed.
stmt.Params["id"] = i
stmt.Params["value"] = test.val
statements = append(statements, stmt)
}
_, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
rowCounts, err := tx.BatchUpdate(ctx, statements)
if err != nil {
return err
}
if len(rowCounts) != len(tests) {
return fmt.Errorf("rowCounts length mismatch\nGot: %v\nWant: %v", len(rowCounts), len(tests))
}
for i, c := range rowCounts {
if c != 1 {
return fmt.Errorf("row count mismatch for row %v:\nGot: %v\nWant: %v", i, c, 1)
}
}
return nil
})
if err != nil {
t.Fatalf("failed to insert values using DML: %v", err)
}
// Delete all the rows so we can insert them using mutations as well.
_, err = client.Apply(ctx, []*Mutation{Delete("Types", AllKeys())})
if err != nil {
t.Fatalf("failed to delete all rows: %v", err)
}
}

// See https://github.com/GoogleCloudPlatform/cloud-spanner-emulator/issues/31
if !isEmulatorEnvSet() {
tests = append(tests, []struct {
col string
val interface{}
want interface{}
}{
{col: "JSON", val: NullJSON{msg, true}, want: NullJSON{unmarshalledJSONstruct, true}},
{col: "JSON", val: NullJSON{msg, false}, want: NullJSON{}},
{col: "JSON", val: nil, want: NullJSON{}},
{col: "JSONArray", val: []NullJSON(nil)},
{col: "JSONArray", val: []NullJSON{}},
{col: "JSONArray", val: []NullJSON{{msg, true}, {msg, true}, {}}, want: []NullJSON{{unmarshalledJSONstruct, true}, {unmarshalledJSONstruct, true}, {}}},
{col: "Date", val: nil, want: NullDate{}},
{col: "Timestamp", val: nil, want: NullTime{}},
}...)
}

// Write rows into table first using DML.
statements := make([]Statement, 0)
for i, test := range tests {
stmt := NewStatement(fmt.Sprintf("INSERT INTO Types (RowId, `%s`) VALUES (@id, @value)", test.col))
// Note: We are not setting the parameter type here to ensure that it
// can be automatically recognized when it is actually needed.
stmt.Params["id"] = i
stmt.Params["value"] = test.val
statements = append(statements, stmt)
}
_, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, tx *ReadWriteTransaction) error {
rowCounts, err := tx.BatchUpdate(ctx, statements)
if err != nil {
return err
}
if len(rowCounts) != len(tests) {
return fmt.Errorf("rowCounts length mismatch\nGot: %v\nWant: %v", len(rowCounts), len(tests))
}
for i, c := range rowCounts {
if c != 1 {
return fmt.Errorf("row count mismatch for row %v:\nGot: %v\nWant: %v", i, c, 1)
}
}
return nil
})
if err != nil {
t.Fatalf("failed to insert values using DML: %v", err)
}
// Delete all the rows so we can insert them using mutations as well.
_, err = client.Apply(ctx, []*Mutation{Delete("Types", AllKeys())})
if err != nil {
t.Fatalf("failed to delete all rows: %v", err)
}

// Verify that we can insert the rows using mutations.
var muts []*Mutation
for i, test := range tests {
Expand Down