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