// stm: @unit package dagstore import ( "context" "io" "net/url" "strings" "testing" "github.com/golang/mock/gomock" blocksutil "github.com/ipfs/go-ipfs-blocksutil" "github.com/stretchr/testify/require" "github.com/filecoin-project/dagstore/mount" mock_dagstore "github.com/filecoin-project/lotus/markets/dagstore/mocks" ) func TestLotusMount(t *testing.T) { //stm: @MARKET_DAGSTORE_FETCH_UNSEALED_PIECE_001, @MARKET_DAGSTORE_GET_UNPADDED_CAR_SIZE_001 //stm: @MARKET_DAGSTORE_IS_PIECE_UNSEALED_001 ctx := context.Background() bgen := blocksutil.NewBlockGenerator() cid := bgen.Next().Cid() mockCtrl := gomock.NewController(t) // when test is done, assert expectations on all mock objects. defer mockCtrl.Finish() // create a mock lotus api that returns the reader we want mockLotusMountAPI := mock_dagstore.NewMockMinerAPI(mockCtrl) mockLotusMountAPI.EXPECT().IsUnsealed(gomock.Any(), cid).Return(true, nil).Times(1) mr1 := struct { io.ReadCloser io.ReaderAt io.Seeker }{ ReadCloser: io.NopCloser(strings.NewReader("testing")), ReaderAt: nil, Seeker: nil, } mr2 := struct { io.ReadCloser io.ReaderAt io.Seeker }{ ReadCloser: io.NopCloser(strings.NewReader("testing")), ReaderAt: nil, Seeker: nil, } mockLotusMountAPI.EXPECT().FetchUnsealedPiece(gomock.Any(), cid).Return(mr1, nil).Times(1) mockLotusMountAPI.EXPECT().FetchUnsealedPiece(gomock.Any(), cid).Return(mr2, nil).Times(1) mockLotusMountAPI.EXPECT().GetUnpaddedCARSize(ctx, cid).Return(uint64(100), nil).Times(1) mnt, err := NewLotusMount(cid, mockLotusMountAPI) require.NoError(t, err) info := mnt.Info() require.Equal(t, info.Kind, mount.KindRemote) // fetch and assert success rd, err := mnt.Fetch(context.Background()) require.NoError(t, err) bz, err := io.ReadAll(rd) require.NoError(t, err) require.NoError(t, rd.Close()) require.Equal(t, []byte("testing"), bz) stat, err := mnt.Stat(ctx) require.NoError(t, err) require.EqualValues(t, 100, stat.Size) // serialize url then deserialize from mount template -> should get back // the same mount url := mnt.Serialize() mnt2 := mountTemplate(mockLotusMountAPI) err = mnt2.Deserialize(url) require.NoError(t, err) // fetching on this mount should get us back the same data. rd, err = mnt2.Fetch(context.Background()) require.NoError(t, err) bz, err = io.ReadAll(rd) require.NoError(t, err) require.NoError(t, rd.Close()) require.Equal(t, []byte("testing"), bz) } func TestLotusMountDeserialize(t *testing.T) { //stm: @MARKET_DAGSTORE_DESERIALIZE_CID_001 api := &minerAPI{} bgen := blocksutil.NewBlockGenerator() cid := bgen.Next().Cid() // success us := lotusScheme + "://" + cid.String() u, err := url.Parse(us) require.NoError(t, err) mnt := mountTemplate(api) err = mnt.Deserialize(u) require.NoError(t, err) require.Equal(t, cid, mnt.PieceCid) require.Equal(t, api, mnt.API) // fails if cid is not valid us = lotusScheme + "://" + "rand" u, err = url.Parse(us) require.NoError(t, err) err = mnt.Deserialize(u) require.Error(t, err) require.Contains(t, err.Error(), "failed to parse PieceCid") } func TestLotusMountRegistration(t *testing.T) { //stm: @MARKET_DAGSTORE_FETCH_UNSEALED_PIECE_001, @MARKET_DAGSTORE_GET_UNPADDED_CAR_SIZE_001 //stm: @MARKET_DAGSTORE_IS_PIECE_UNSEALED_001 ctx := context.Background() bgen := blocksutil.NewBlockGenerator() cid := bgen.Next().Cid() // success us := lotusScheme + "://" + cid.String() u, err := url.Parse(us) require.NoError(t, err) mockCtrl := gomock.NewController(t) // when test is done, assert expectations on all mock objects. defer mockCtrl.Finish() mockLotusMountAPI := mock_dagstore.NewMockMinerAPI(mockCtrl) registry := mount.NewRegistry() err = registry.Register(lotusScheme, mountTemplate(mockLotusMountAPI)) require.NoError(t, err) mnt, err := registry.Instantiate(u) require.NoError(t, err) mockLotusMountAPI.EXPECT().IsUnsealed(ctx, cid).Return(true, nil) mockLotusMountAPI.EXPECT().GetUnpaddedCARSize(ctx, cid).Return(uint64(100), nil).Times(1) stat, err := mnt.Stat(context.Background()) require.NoError(t, err) require.EqualValues(t, 100, stat.Size) require.True(t, stat.Ready) }