-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
spanner_test.go
171 lines (156 loc) · 5.29 KB
/
spanner_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package spanner
import (
"fmt"
"os"
"testing"
"github.com/golang-migrate/migrate/v4"
dt "github.com/golang-migrate/migrate/v4/database/testing"
_ "github.com/golang-migrate/migrate/v4/source/file"
"cloud.google.com/go/spanner/spannertest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// withSpannerEmulator is not thread-safe and cannot be used with parallel tests since it sets the emulator
func withSpannerEmulator(t *testing.T, testFunc func(t *testing.T)) {
t.Helper()
srv, err := spannertest.NewServer("localhost:0")
if err != nil {
t.Fatal("Failed to create Spanner emulator:", err)
}
// This is not thread-safe
if err := os.Setenv("SPANNER_EMULATOR_HOST", srv.Addr); err != nil {
t.Fatal("Failed to set SPANNER_EMULATOR_HOST env var:", err)
}
defer srv.Close()
testFunc(t)
}
const db = "projects/abc/instances/def/databases/testdb"
func Test(t *testing.T) {
withSpannerEmulator(t, func(t *testing.T) {
uri := fmt.Sprintf("spanner://%s", db)
s := &Spanner{}
d, err := s.Open(uri)
if err != nil {
t.Fatal(err)
}
dt.Test(t, d, []byte("CREATE TABLE test (id BOOL) PRIMARY KEY (id)"))
})
}
func TestMigrate(t *testing.T) {
withSpannerEmulator(t, func(t *testing.T) {
s := &Spanner{}
uri := fmt.Sprintf("spanner://%s", db)
d, err := s.Open(uri)
if err != nil {
t.Fatal(err)
}
m, err := migrate.NewWithDatabaseInstance("file://./examples/migrations", uri, d)
if err != nil {
t.Fatal(err)
}
dt.TestMigrate(t, m)
})
}
func TestCleanStatements(t *testing.T) {
testCases := []struct {
name string
multiStatement string
expected []string
}{
{
name: "no statement",
multiStatement: "",
expected: []string{},
},
{
name: "single statement, single line, no semicolon, no comment",
multiStatement: "CREATE TABLE table_name (id STRING(255) NOT NULL) PRIMARY KEY (id)",
expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"},
},
{
name: "single statement, multi line, no semicolon, no comment",
multiStatement: `CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY (id)`,
expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"},
},
{
name: "single statement, single line, with semicolon, no comment",
multiStatement: "CREATE TABLE table_name (id STRING(255) NOT NULL) PRIMARY KEY (id);",
expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"},
},
{
name: "single statement, multi line, with semicolon, no comment",
multiStatement: `CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY (id);`,
expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"},
},
{
name: "multi statement, with trailing semicolon. no comment",
// From https://github.com/mattes/migrate/pull/281
multiStatement: `CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY(id);
CREATE INDEX table_name_id_idx ON table_name (id);`,
expected: []string{`CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"},
},
{
name: "multi statement, no trailing semicolon, no comment",
// From https://github.com/mattes/migrate/pull/281
multiStatement: `CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY(id);
CREATE INDEX table_name_id_idx ON table_name (id)`,
expected: []string{`CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"},
},
{
name: "multi statement, no trailing semicolon, standalone comment",
// From https://github.com/mattes/migrate/pull/281
multiStatement: `CREATE TABLE table_name (
-- standalone comment
id STRING(255) NOT NULL,
) PRIMARY KEY(id);
CREATE INDEX table_name_id_idx ON table_name (id)`,
expected: []string{`CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"},
},
{
name: "multi statement, no trailing semicolon, inline comment",
// From https://github.com/mattes/migrate/pull/281
multiStatement: `CREATE TABLE table_name (
id STRING(255) NOT NULL, -- inline comment
) PRIMARY KEY(id);
CREATE INDEX table_name_id_idx ON table_name (id)`,
expected: []string{`CREATE TABLE table_name (
id STRING(255) NOT NULL,
) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"},
},
{
name: "alter table with SET OPTIONS",
multiStatement: `ALTER TABLE users ALTER COLUMN created
SET OPTIONS (allow_commit_timestamp=true);`,
expected: []string{"ALTER TABLE users ALTER COLUMN created SET OPTIONS (allow_commit_timestamp = true)"},
},
{
name: "column with NUMERIC type",
multiStatement: `CREATE TABLE table_name (
id STRING(255) NOT NULL,
sum NUMERIC,
) PRIMARY KEY (id)`,
expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n sum NUMERIC,\n) PRIMARY KEY(id)"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
stmts, err := cleanStatements([]byte(tc.multiStatement))
require.NoError(t, err, "Error cleaning statements")
assert.Equal(t, tc.expected, stmts)
})
}
}