|
| 1 | +package cmd |
| 2 | + |
| 3 | +import ( |
| 4 | + "io" |
| 5 | + "net/http" |
| 6 | + "net/http/httptest" |
| 7 | + "os" |
| 8 | + "path/filepath" |
| 9 | + "strings" |
| 10 | + "testing" |
| 11 | + |
| 12 | + "github.com/rs/zerolog" |
| 13 | + "github.com/spf13/cobra" |
| 14 | + "github.com/stretchr/testify/mock" |
| 15 | + "github.com/stretchr/testify/require" |
| 16 | + "golang.org/x/net/http2" |
| 17 | + "golang.org/x/net/http2/h2c" |
| 18 | + |
| 19 | + "github.com/evstack/ev-node/pkg/config" |
| 20 | + "github.com/evstack/ev-node/pkg/rpc/server" |
| 21 | + "github.com/evstack/ev-node/test/mocks" |
| 22 | + "github.com/evstack/ev-node/types/pb/evnode/v1/v1connect" |
| 23 | +) |
| 24 | + |
| 25 | +func TestBackupCmd_Success(t *testing.T) { |
| 26 | + t.Parallel() |
| 27 | + |
| 28 | + mockStore := mocks.NewMockStore(t) |
| 29 | + |
| 30 | + mockStore.On("Height", mock.Anything).Return(uint64(15), nil) |
| 31 | + mockStore.On("Backup", mock.Anything, mock.Anything, uint64(9)).Run(func(args mock.Arguments) { |
| 32 | + writer := args.Get(1).(io.Writer) |
| 33 | + _, _ = writer.Write([]byte("chunk-1")) |
| 34 | + _, _ = writer.Write([]byte("chunk-2")) |
| 35 | + }).Return(uint64(21), nil) |
| 36 | + |
| 37 | + logger := zerolog.Nop() |
| 38 | + storeServer := server.NewStoreServer(mockStore, logger) |
| 39 | + mux := http.NewServeMux() |
| 40 | + storePath, storeHandler := v1connect.NewStoreServiceHandler(storeServer) |
| 41 | + mux.Handle(storePath, storeHandler) |
| 42 | + |
| 43 | + httpServer := httptest.NewServer(h2c.NewHandler(mux, &http2.Server{})) |
| 44 | + defer httpServer.Close() |
| 45 | + |
| 46 | + tempDir, err := os.MkdirTemp("", "evnode-backup-*") |
| 47 | + require.NoError(t, err) |
| 48 | + t.Cleanup(func() { |
| 49 | + _ = os.RemoveAll(tempDir) |
| 50 | + }) |
| 51 | + |
| 52 | + backupCmd := NewBackupCmd() |
| 53 | + config.AddFlags(backupCmd) |
| 54 | + |
| 55 | + rootCmd := &cobra.Command{Use: "root"} |
| 56 | + config.AddGlobalFlags(rootCmd, "test") |
| 57 | + rootCmd.AddCommand(backupCmd) |
| 58 | + |
| 59 | + outPath := filepath.Join(tempDir, "snapshot.badger") |
| 60 | + rpcAddr := strings.TrimPrefix(httpServer.URL, "http://") |
| 61 | + |
| 62 | + output, err := executeCommandC( |
| 63 | + rootCmd, |
| 64 | + "backup", |
| 65 | + "--home="+tempDir, |
| 66 | + "--evnode.rpc.address="+rpcAddr, |
| 67 | + "--output", outPath, |
| 68 | + "--target-height", "12", |
| 69 | + "--since-version", "9", |
| 70 | + ) |
| 71 | + |
| 72 | + require.NoError(t, err, "command failed: %s", output) |
| 73 | + |
| 74 | + data, readErr := os.ReadFile(outPath) |
| 75 | + require.NoError(t, readErr) |
| 76 | + require.Equal(t, "chunk-1chunk-2", string(data)) |
| 77 | + |
| 78 | + require.Contains(t, output, "Backup saved to") |
| 79 | + require.Contains(t, output, "Current height: 15") |
| 80 | + require.Contains(t, output, "Target height: 12") |
| 81 | + require.Contains(t, output, "Since version: 9") |
| 82 | + require.Contains(t, output, "Last version: 21") |
| 83 | + |
| 84 | + mockStore.AssertExpectations(t) |
| 85 | +} |
| 86 | + |
| 87 | +func TestBackupCmd_ExistingFileWithoutForce(t *testing.T) { |
| 88 | + t.Parallel() |
| 89 | + |
| 90 | + mockStore := mocks.NewMockStore(t) |
| 91 | + logger := zerolog.Nop() |
| 92 | + storeServer := server.NewStoreServer(mockStore, logger) |
| 93 | + mux := http.NewServeMux() |
| 94 | + storePath, storeHandler := v1connect.NewStoreServiceHandler(storeServer) |
| 95 | + mux.Handle(storePath, storeHandler) |
| 96 | + |
| 97 | + httpServer := httptest.NewServer(h2c.NewHandler(mux, &http2.Server{})) |
| 98 | + defer httpServer.Close() |
| 99 | + |
| 100 | + tempDir, err := os.MkdirTemp("", "evnode-backup-existing-*") |
| 101 | + require.NoError(t, err) |
| 102 | + t.Cleanup(func() { |
| 103 | + _ = os.RemoveAll(tempDir) |
| 104 | + }) |
| 105 | + |
| 106 | + outPath := filepath.Join(tempDir, "snapshot.badger") |
| 107 | + require.NoError(t, os.WriteFile(outPath, []byte("existing"), 0o600)) |
| 108 | + |
| 109 | + backupCmd := NewBackupCmd() |
| 110 | + config.AddFlags(backupCmd) |
| 111 | + |
| 112 | + rootCmd := &cobra.Command{Use: "root"} |
| 113 | + config.AddGlobalFlags(rootCmd, "test") |
| 114 | + rootCmd.AddCommand(backupCmd) |
| 115 | + |
| 116 | + rpcAddr := strings.TrimPrefix(httpServer.URL, "http://") |
| 117 | + |
| 118 | + output, err := executeCommandC( |
| 119 | + rootCmd, |
| 120 | + "backup", |
| 121 | + "--home="+tempDir, |
| 122 | + "--evnode.rpc.address="+rpcAddr, |
| 123 | + "--output", outPath, |
| 124 | + ) |
| 125 | + |
| 126 | + require.Error(t, err) |
| 127 | + require.Contains(t, output, "already exists (use --force to overwrite)") |
| 128 | +} |
0 commit comments