github.com/supabase/cli@v1.168.1/internal/stop/stop_test.go (about) 1 package stop 2 3 import ( 4 "context" 5 "errors" 6 "io" 7 "net/http" 8 "os" 9 "testing" 10 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/api/types/volume" 13 "github.com/spf13/afero" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 "github.com/supabase/cli/internal/testing/apitest" 17 "github.com/supabase/cli/internal/utils" 18 "gopkg.in/h2non/gock.v1" 19 ) 20 21 func TestStopCommand(t *testing.T) { 22 t.Run("stops containers with backup", func(t *testing.T) { 23 // Setup in-memory fs 24 fsys := afero.NewMemMapFs() 25 require.NoError(t, utils.WriteConfig(fsys, false)) 26 // Setup mock docker 27 require.NoError(t, apitest.MockDocker(utils.Docker)) 28 defer gock.OffAll() 29 gock.New(utils.Docker.DaemonHost()). 30 Get("/v" + utils.Docker.ClientVersion() + "/containers/json"). 31 Reply(http.StatusOK). 32 JSON([]types.Container{}) 33 gock.New(utils.Docker.DaemonHost()). 34 Post("/v" + utils.Docker.ClientVersion() + "/containers/prune"). 35 Reply(http.StatusOK). 36 JSON(types.ContainersPruneReport{}) 37 gock.New(utils.Docker.DaemonHost()). 38 Post("/v" + utils.Docker.ClientVersion() + "/networks/prune"). 39 Reply(http.StatusOK). 40 JSON(types.NetworksPruneReport{}) 41 gock.New(utils.Docker.DaemonHost()). 42 Get("/v" + utils.Docker.ClientVersion() + "/volumes"). 43 Reply(http.StatusOK). 44 JSON(volume.ListResponse{Volumes: []*volume.Volume{{ 45 Name: utils.DbId, 46 }}}) 47 // Run test 48 err := Run(context.Background(), true, "", fsys) 49 // Check error 50 assert.NoError(t, err) 51 assert.Empty(t, apitest.ListUnmatchedRequests()) 52 }) 53 54 t.Run("throws error on invalid config", func(t *testing.T) { 55 // Setup in-memory fs 56 fsys := afero.NewMemMapFs() 57 // Run test 58 err := Run(context.Background(), false, "", fsys) 59 // Check error 60 assert.ErrorIs(t, err, os.ErrNotExist) 61 }) 62 63 t.Run("throws error on stop failure", func(t *testing.T) { 64 // Setup in-memory fs 65 fsys := afero.NewMemMapFs() 66 require.NoError(t, utils.WriteConfig(fsys, false)) 67 // Setup mock docker 68 require.NoError(t, apitest.MockDocker(utils.Docker)) 69 defer gock.OffAll() 70 gock.New(utils.Docker.DaemonHost()). 71 Get("/v" + utils.Docker.ClientVersion() + "/containers/json"). 72 Reply(http.StatusServiceUnavailable) 73 // Run test 74 err := Run(context.Background(), false, "test", afero.NewReadOnlyFs(fsys)) 75 // Check error 76 assert.ErrorContains(t, err, "request returned Service Unavailable for API route and version") 77 assert.Empty(t, apitest.ListUnmatchedRequests()) 78 }) 79 } 80 81 func TestStopServices(t *testing.T) { 82 t.Run("stops all services", func(t *testing.T) { 83 containers := []types.Container{{ID: "c1", State: "running"}, {ID: "c2"}} 84 // Setup mock docker 85 require.NoError(t, apitest.MockDocker(utils.Docker)) 86 defer gock.OffAll() 87 gock.New(utils.Docker.DaemonHost()). 88 Get("/v" + utils.Docker.ClientVersion() + "/containers/json"). 89 Reply(http.StatusOK). 90 JSON(containers) 91 gock.New(utils.Docker.DaemonHost()). 92 Post("/v" + utils.Docker.ClientVersion() + "/containers/" + containers[0].ID + "/stop"). 93 Reply(http.StatusOK) 94 gock.New(utils.Docker.DaemonHost()). 95 Post("/v" + utils.Docker.ClientVersion() + "/containers/prune"). 96 Reply(http.StatusOK). 97 JSON(types.ContainersPruneReport{}) 98 gock.New(utils.Docker.DaemonHost()). 99 Post("/v" + utils.Docker.ClientVersion() + "/networks/prune"). 100 Reply(http.StatusOK). 101 JSON(types.NetworksPruneReport{}) 102 // Run test 103 err := stop(context.Background(), true, io.Discard) 104 // Check error 105 assert.NoError(t, err) 106 assert.Empty(t, apitest.ListUnmatchedRequests()) 107 }) 108 109 t.Run("removes data volumes", func(t *testing.T) { 110 utils.DbId = "test-db" 111 utils.ConfigId = "test-config" 112 utils.StorageId = "test-storage" 113 utils.EdgeRuntimeId = "test-functions" 114 utils.InbucketId = "test-inbucket" 115 // Setup mock docker 116 require.NoError(t, apitest.MockDocker(utils.Docker)) 117 defer gock.OffAll() 118 apitest.MockDockerStop(utils.Docker) 119 // Run test 120 err := stop(context.Background(), false, io.Discard) 121 // Check error 122 assert.NoError(t, err) 123 assert.Empty(t, apitest.ListUnmatchedRequests()) 124 }) 125 126 t.Run("throws error on prune failure", func(t *testing.T) { 127 // Setup mock docker 128 require.NoError(t, apitest.MockDocker(utils.Docker)) 129 defer gock.OffAll() 130 gock.New(utils.Docker.DaemonHost()). 131 Get("/v" + utils.Docker.ClientVersion() + "/containers/json"). 132 Reply(http.StatusOK). 133 JSON([]types.Container{}) 134 gock.New(utils.Docker.DaemonHost()). 135 Post("/v" + utils.Docker.ClientVersion() + "/containers/prune"). 136 ReplyError(errors.New("network error")) 137 // Run test 138 err := stop(context.Background(), true, io.Discard) 139 // Check error 140 assert.ErrorContains(t, err, "network error") 141 assert.Empty(t, apitest.ListUnmatchedRequests()) 142 }) 143 }