github.com/Elate-DevOps/migrate/v4@v4.0.12/database/spanner/spanner_test.go (about) 1 package spanner 2 3 import ( 4 "fmt" 5 "os" 6 "testing" 7 8 "github.com/Elate-DevOps/migrate/v4" 9 10 dt "github.com/Elate-DevOps/migrate/v4/database/testing" 11 _ "github.com/Elate-DevOps/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 // withSpannerEmulator is not thread-safe and cannot be used with parallel tests since it sets the emulator 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 // This is not thread-safe 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 const db = "projects/abc/instances/def/databases/testdb" 34 35 func Test(t *testing.T) { 36 withSpannerEmulator(t, func(t *testing.T) { 37 uri := fmt.Sprintf("spanner://%s", db) 38 s := &Spanner{} 39 d, err := s.Open(uri) 40 if err != nil { 41 t.Fatal(err) 42 } 43 dt.Test(t, d, []byte("CREATE TABLE test (id BOOL) PRIMARY KEY (id)")) 44 }) 45 } 46 47 func TestMigrate(t *testing.T) { 48 withSpannerEmulator(t, func(t *testing.T) { 49 s := &Spanner{} 50 uri := fmt.Sprintf("spanner://%s", db) 51 d, err := s.Open(uri) 52 if err != nil { 53 t.Fatal(err) 54 } 55 m, err := migrate.NewWithDatabaseInstance("file://./examples/migrations", uri, d) 56 if err != nil { 57 t.Fatal(err) 58 } 59 dt.TestMigrate(t, m) 60 }) 61 } 62 63 func TestCleanStatements(t *testing.T) { 64 testCases := []struct { 65 name string 66 multiStatement string 67 expected []string 68 }{ 69 { 70 name: "no statement", 71 multiStatement: "", 72 expected: []string{}, 73 }, 74 { 75 name: "single statement, single line, no semicolon, no comment", 76 multiStatement: "CREATE TABLE table_name (id STRING(255) NOT NULL) PRIMARY KEY (id)", 77 expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"}, 78 }, 79 { 80 name: "single statement, multi line, no semicolon, no comment", 81 multiStatement: `CREATE TABLE table_name ( 82 id STRING(255) NOT NULL, 83 ) PRIMARY KEY (id)`, 84 expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"}, 85 }, 86 { 87 name: "single statement, single line, with semicolon, no comment", 88 multiStatement: "CREATE TABLE table_name (id STRING(255) NOT NULL) PRIMARY KEY (id);", 89 expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"}, 90 }, 91 { 92 name: "single statement, multi line, with semicolon, no comment", 93 multiStatement: `CREATE TABLE table_name ( 94 id STRING(255) NOT NULL, 95 ) PRIMARY KEY (id);`, 96 expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n) PRIMARY KEY(id)"}, 97 }, 98 { 99 name: "multi statement, with trailing semicolon. no comment", 100 // From https://github.com/mattes/migrate/pull/281 101 multiStatement: `CREATE TABLE table_name ( 102 id STRING(255) NOT NULL, 103 ) PRIMARY KEY(id); 104 105 CREATE INDEX table_name_id_idx ON table_name (id);`, 106 expected: []string{`CREATE TABLE table_name ( 107 id STRING(255) NOT NULL, 108 ) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"}, 109 }, 110 { 111 name: "multi statement, no trailing semicolon, no comment", 112 // From https://github.com/mattes/migrate/pull/281 113 multiStatement: `CREATE TABLE table_name ( 114 id STRING(255) NOT NULL, 115 ) PRIMARY KEY(id); 116 117 CREATE INDEX table_name_id_idx ON table_name (id)`, 118 expected: []string{`CREATE TABLE table_name ( 119 id STRING(255) NOT NULL, 120 ) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"}, 121 }, 122 { 123 name: "multi statement, no trailing semicolon, standalone comment", 124 // From https://github.com/mattes/migrate/pull/281 125 multiStatement: `CREATE TABLE table_name ( 126 -- standalone comment 127 id STRING(255) NOT NULL, 128 ) PRIMARY KEY(id); 129 130 CREATE INDEX table_name_id_idx ON table_name (id)`, 131 expected: []string{`CREATE TABLE table_name ( 132 id STRING(255) NOT NULL, 133 ) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"}, 134 }, 135 { 136 name: "multi statement, no trailing semicolon, inline comment", 137 // From https://github.com/mattes/migrate/pull/281 138 multiStatement: `CREATE TABLE table_name ( 139 id STRING(255) NOT NULL, -- inline comment 140 ) PRIMARY KEY(id); 141 142 CREATE INDEX table_name_id_idx ON table_name (id)`, 143 expected: []string{`CREATE TABLE table_name ( 144 id STRING(255) NOT NULL, 145 ) PRIMARY KEY(id)`, "CREATE INDEX table_name_id_idx ON table_name(id)"}, 146 }, 147 { 148 name: "alter table with SET OPTIONS", 149 multiStatement: `ALTER TABLE users ALTER COLUMN created 150 SET OPTIONS (allow_commit_timestamp=true);`, 151 expected: []string{"ALTER TABLE users ALTER COLUMN created SET OPTIONS (allow_commit_timestamp = true)"}, 152 }, 153 { 154 name: "column with NUMERIC type", 155 multiStatement: `CREATE TABLE table_name ( 156 id STRING(255) NOT NULL, 157 sum NUMERIC, 158 ) PRIMARY KEY (id)`, 159 expected: []string{"CREATE TABLE table_name (\n id STRING(255) NOT NULL,\n sum NUMERIC,\n) PRIMARY KEY(id)"}, 160 }, 161 } 162 163 for _, tc := range testCases { 164 t.Run(tc.name, func(t *testing.T) { 165 stmts, err := cleanStatements([]byte(tc.multiStatement)) 166 require.NoError(t, err, "Error cleaning statements") 167 assert.Equal(t, tc.expected, stmts) 168 }) 169 } 170 }