github.com/scraniel/migrate@v0.0.0-20230320185700-339088f36cee/database/spanner/spanner_test.go (about)

     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  // 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  
    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  			// From https://github.com/mattes/migrate/pull/281
   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  			// From https://github.com/mattes/migrate/pull/281
   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  			// From https://github.com/mattes/migrate/pull/281
   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  			// From https://github.com/mattes/migrate/pull/281
   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  }