Skip to content

Commit

Permalink
chore: check local database before loading config
Browse files Browse the repository at this point in the history
  • Loading branch information
sweatybridge committed Feb 19, 2024
1 parent 3fe9ce5 commit 88e78c0
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 95 deletions.
3 changes: 2 additions & 1 deletion internal/db/diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/supabase/cli/internal/db/start"
"github.com/supabase/cli/internal/migration/history"
"github.com/supabase/cli/internal/testing/apitest"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/testing/pgtest"
"github.com/supabase/cli/internal/utils"
"gopkg.in/h2non/gock.v1"
Expand Down Expand Up @@ -174,7 +175,7 @@ func TestMigrateShadow(t *testing.T) {

t.Run("throws error on permission denied", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir}
// Run test
err := MigrateShadowDatabase(context.Background(), "", fsys)
// Check error
Expand Down
3 changes: 2 additions & 1 deletion internal/db/pull/pull_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/supabase/cli/internal/db/reset"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/testing/apitest"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/testing/pgtest"
"github.com/supabase/cli/internal/utils"
"gopkg.in/h2non/gock.v1"
Expand Down Expand Up @@ -217,7 +218,7 @@ func TestPullSchema(t *testing.T) {
func TestSyncRemote(t *testing.T) {
t.Run("throws error on permission denied", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir}
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand Down
2 changes: 1 addition & 1 deletion internal/db/push/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
return err
}
if len(pending) == 0 {
fmt.Println("Linked project is up to date.")
fmt.Println("Remote database is up to date.")
return nil
}
// Push pending migrations
Expand Down
11 changes: 1 addition & 10 deletions internal/db/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,7 @@ const (
DISABLE_PGTAP = "drop extension if exists pgtap"
)

func Run(ctx context.Context, testFiles []string, dbConfig pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
// Sanity checks.
if err := utils.LoadConfigFS(fsys); err != nil {
return err
}

return pgProve(ctx, testFiles, dbConfig, options...)
}

func pgProve(ctx context.Context, testFiles []string, config pgconn.Config, options ...func(*pgx.ConnConfig)) error {
func Run(ctx context.Context, testFiles []string, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
// Build test command
cmd := []string{"pg_prove", "--ext", ".pg", "--ext", ".sql", "-r"}
for _, fp := range testFiles {
Expand Down
75 changes: 36 additions & 39 deletions internal/db/test/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package test
import (
"context"
"errors"
"os"
"testing"

"github.com/jackc/pgconn"
Expand All @@ -25,28 +24,60 @@ var dbConfig = pgconn.Config{
Database: "postgres",
}

func TestPgProve(t *testing.T) {
func TestRunCommand(t *testing.T) {
t.Run("runs tests with pg_prove", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, utils.WriteConfig(fsys, false))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(ENABLE_PGTAP).
Reply("CREATE EXTENSION").
Query(DISABLE_PGTAP).
Reply("DROP EXTENSION")
// Setup mock docker
require.NoError(t, apitest.MockDocker(utils.Docker))
defer gock.OffAll()
containerId := "test-pg-prove"
apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.PgProveImage), containerId)
require.NoError(t, apitest.MockDockerLogs(utils.Docker, containerId, "Result: SUCCESS"))
// Run test
err := Run(context.Background(), []string{"nested"}, dbConfig, fsys, conn.Intercept)
// Check error
assert.NoError(t, err)
})

t.Run("throws error on connect failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, utils.WriteConfig(fsys, false))
// Run test
err := pgProve(context.Background(), nil, dbConfig)
err := Run(context.Background(), nil, dbConfig, fsys)
// Check error
assert.ErrorContains(t, err, "failed to connect to postgres")
})

t.Run("throws error on pgtap failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, utils.WriteConfig(fsys, false))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(ENABLE_PGTAP).
ReplyError(pgerrcode.DuplicateObject, `extension "pgtap" already exists, skipping`)
// Run test
err := pgProve(context.Background(), nil, dbConfig, conn.Intercept)
err := Run(context.Background(), nil, dbConfig, fsys, conn.Intercept)
// Check error
assert.ErrorContains(t, err, "failed to enable pgTAP")
})

t.Run("throws error on network failure", func(t *testing.T) {
errNetwork := errors.New("network error")
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, utils.WriteConfig(fsys, false))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand All @@ -61,43 +92,9 @@ func TestPgProve(t *testing.T) {
Get("/v" + utils.Docker.ClientVersion() + "/images/" + utils.GetRegistryImageUrl(utils.PgProveImage) + "/json").
ReplyError(errNetwork)
// Run test
err := pgProve(context.Background(), nil, dbConfig, conn.Intercept)
err := Run(context.Background(), nil, dbConfig, fsys, conn.Intercept)
// Check error
assert.ErrorIs(t, err, errNetwork)
assert.Empty(t, apitest.ListUnmatchedRequests())
})
}

func TestRunCommand(t *testing.T) {
t.Run("runs tests with pg_prove", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, utils.WriteConfig(fsys, false))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(ENABLE_PGTAP).
Reply("CREATE EXTENSION").
Query(DISABLE_PGTAP).
Reply("DROP EXTENSION")
// Setup mock docker
require.NoError(t, apitest.MockDocker(utils.Docker))
defer gock.OffAll()
containerId := "test-pg-prove"
apitest.MockDockerStart(utils.Docker, utils.GetRegistryImageUrl(utils.PgProveImage), containerId)
require.NoError(t, apitest.MockDockerLogs(utils.Docker, containerId, "Result: SUCCESS"))
// Run test
err := Run(context.Background(), []string{"nested"}, dbConfig, fsys, conn.Intercept)
// Check error
assert.NoError(t, err)
})

t.Run("throws error on missing config", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
err := Run(context.Background(), nil, dbConfig, fsys)
// Check error
assert.ErrorIs(t, err, os.ErrNotExist)
})
}
6 changes: 3 additions & 3 deletions internal/migration/apply/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ func TestMigrateDatabase(t *testing.T) {
assert.NoError(t, MigrateAndSeed(context.Background(), "", nil, afero.NewMemMapFs()))
})

t.Run("throws error on write failure", func(t *testing.T) {
t.Run("throws error on open failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir}
// Run test
err := MigrateAndSeed(context.Background(), "", nil, afero.NewReadOnlyFs(fsys))
err := MigrateAndSeed(context.Background(), "", nil, fsys)
// Check error
assert.ErrorIs(t, err, os.ErrPermission)
})
Expand Down
5 changes: 1 addition & 4 deletions internal/migration/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,8 @@ func LoadLocalMigrations(fsys afero.Fs) ([]string, error) {
}

func LoadPartialMigrations(version string, fsys afero.Fs) ([]string, error) {
if err := utils.MkdirIfNotExistFS(fsys, utils.MigrationsDir); err != nil {
return nil, err
}
localMigrations, err := afero.ReadDir(fsys, utils.MigrationsDir)
if err != nil {
if err != nil && !errors.Is(err, os.ErrNotExist) {
return nil, errors.Errorf("failed to read directory: %w", err)
}
var names []string
Expand Down
38 changes: 9 additions & 29 deletions internal/migration/list/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package list

import (
"context"
"io/fs"
"os"
"path/filepath"
"strings"
"testing"
Expand All @@ -12,6 +12,7 @@ import (
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/testing/pgtest"
"github.com/supabase/cli/internal/utils"
)
Expand Down Expand Up @@ -48,18 +49,18 @@ func TestMigrationList(t *testing.T) {
assert.ErrorContains(t, err, "invalid port (outside range)")
})

t.Run("throws error on local failure", func(t *testing.T) {
t.Run("throws error on open failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir}
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(LIST_MIGRATION_VERSION).
Reply("SELECT 0")
// Run test
err := Run(context.Background(), dbConfig, afero.NewReadOnlyFs(fsys), conn.Intercept)
err := Run(context.Background(), dbConfig, fsys, conn.Intercept)
// Check error
assert.ErrorContains(t, err, "operation not permitted")
assert.ErrorIs(t, err, os.ErrPermission)
})
}

Expand Down Expand Up @@ -110,18 +111,6 @@ func TestRemoteMigrations(t *testing.T) {
})
}

type MockFs struct {
afero.MemMapFs
DenyPath string
}

func (m *MockFs) Open(name string) (afero.File, error) {
if strings.HasPrefix(name, m.DenyPath) {
return nil, fs.ErrPermission
}
return m.MemMapFs.Open(name)
}

func TestLocalMigrations(t *testing.T) {
t.Run("loads migration versions", func(t *testing.T) {
// Setup in-memory fs
Expand Down Expand Up @@ -151,22 +140,13 @@ func TestLocalMigrations(t *testing.T) {
assert.Empty(t, versions)
})

t.Run("throws error on permission denied", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Run test
_, err := LoadLocalVersions(afero.NewReadOnlyFs(fsys))
// Check error
assert.ErrorContains(t, err, "operation not permitted")
})

t.Run("throws error on open failure", func(t *testing.T) {
// Setup in-memory fs
fsys := MockFs{DenyPath: utils.MigrationsDir}
fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir}
// Run test
_, err := LoadLocalVersions(&fsys)
_, err := LoadLocalVersions(fsys)
// Check error
assert.ErrorContains(t, err, "permission denied")
assert.ErrorIs(t, err, os.ErrPermission)
})
}

Expand Down
5 changes: 3 additions & 2 deletions internal/migration/squash/squash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/supabase/cli/internal/migration/history"
"github.com/supabase/cli/internal/migration/repair"
"github.com/supabase/cli/internal/testing/apitest"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/testing/pgtest"
"github.com/supabase/cli/internal/utils"
"gopkg.in/h2non/gock.v1"
Expand Down Expand Up @@ -125,9 +126,9 @@ func TestSquashCommand(t *testing.T) {
func TestSquashVersion(t *testing.T) {
t.Run("throws error on permission denied", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir}
// Run test
err := squashToVersion(context.Background(), "0", afero.NewReadOnlyFs(fsys))
err := squashToVersion(context.Background(), "0", fsys)
// Check error
assert.ErrorIs(t, err, os.ErrPermission)
})
Expand Down
3 changes: 0 additions & 3 deletions internal/migration/up/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ var (
)

func Run(ctx context.Context, includeAll bool, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
if err := utils.LoadConfigFS(fsys); err != nil {
return err
}
conn, err := utils.ConnectByConfig(ctx, config, options...)
if err != nil {
return err
Expand Down
6 changes: 4 additions & 2 deletions internal/migration/up/up_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package up

import (
"context"
"os"
"path/filepath"
"testing"

Expand All @@ -10,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/testing/pgtest"
"github.com/supabase/cli/internal/utils"
)
Expand Down Expand Up @@ -47,7 +49,7 @@ func TestPendingMigrations(t *testing.T) {

t.Run("throws error on local load failure", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewReadOnlyFs(afero.NewMemMapFs())
fsys := &fstest.OpenErrorFs{DenyPath: utils.MigrationsDir}
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand All @@ -61,7 +63,7 @@ func TestPendingMigrations(t *testing.T) {
// Run test
_, err = GetPendingMigrations(ctx, false, mock, fsys)
// Check error
assert.ErrorContains(t, err, "operation not permitted")
assert.ErrorIs(t, err, os.ErrPermission)
})

t.Run("throws error on missing local migration", func(t *testing.T) {
Expand Down

0 comments on commit 88e78c0

Please sign in to comment.