diff --git a/cli/chain.go b/cli/chain.go index 1e41a759c..fe073776a 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -7,6 +7,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "io" "os" "os/exec" "path" @@ -1074,7 +1075,7 @@ var ChainExportCmd = &cli.Command{ return fmt.Errorf("\"recent-stateroots\" has to be greater than %d", build.Finality) } - fi, err := os.Create(cctx.Args().First()) + fi, err := createExportFile(cctx.App, cctx.Args().First()) if err != nil { return err } @@ -1436,3 +1437,16 @@ var chainEncodeParamsCmd = &cli.Command{ return nil }, } + +// createExportFile returns the export file from the app metadata, or creates a new file if it doesn't exist +func createExportFile(app *cli.App, path string) (io.WriteCloser, error) { + if wc, ok := app.Metadata["export-file"]; ok { + return wc.(io.WriteCloser), nil + } + + fi, err := os.Create(path) + if err != nil { + return nil, err + } + return fi, nil +} diff --git a/cli/chain_test.go b/cli/chain_test.go index 70a4a4953..4a553f88a 100644 --- a/cli/chain_test.go +++ b/cli/chain_test.go @@ -472,7 +472,35 @@ func TestChainBisect(t *testing.T) { assert.Contains(t, out, path) } -func TestChainExport(t *testing.T) {} +func TestChainExport(t *testing.T) { + app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("chain", ChainExportCmd)) + defer done() + + mockFile := mockExportFile{new(bytes.Buffer)} + app.Metadata["export-file"] = mockFile + + blk := mock.MkBlock(nil, 0, 0) + ts := mock.TipSet(blk) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + export := make(chan []byte, 2) + expBytes := []byte("whatever") + export <- expBytes + export <- []byte{} // empty slice means export is complete + close(export) + + gomock.InOrder( + mockApi.EXPECT().ChainHead(ctx).Return(ts, nil), + mockApi.EXPECT().ChainExport(ctx, abi.ChainEpoch(0), false, ts.Key()).Return(export, nil), + ) + + err := app.Run([]string{"chain", "export", "whatever.car"}) + assert.NoError(t, err) + + assert.Equal(t, expBytes, mockFile.Bytes()) +} func TestSlashConsensusFault(t *testing.T) {} @@ -481,3 +509,11 @@ func TestChainGasPrice(t *testing.T) {} func TestChainDecode(t *testing.T) {} func TestChainEncode(t *testing.T) {} + +type mockExportFile struct { + *bytes.Buffer +} + +func (mef mockExportFile) Close() error { + return nil +}