@@ -15,6 +15,7 @@ import (
1515 "testing"
1616 "time"
1717
18+ blocks "github.com/ipfs/go-block-format"
1819 "github.com/stretchr/testify/require"
1920
2021 "github.com/sourcenetwork/corekv/memory"
@@ -80,6 +81,48 @@ func TestIsMerged_DeletedBlockIsNotMerged(t *testing.T) {
8081 require .False (t , merged )
8182}
8283
84+ // A CAR import re-puts blocks the node already holds. Storing one unconditionally stamps a fresh
85+ // to-merge marker over a block that already merged, which reads as an abandoned fetch and leaves
86+ // the orphan sweep free to delete a block a live document still links to.
87+ func TestIsMerged_ReputtingAMergedBlockLeavesItMerged (t * testing.T ) {
88+ for _ , tc := range []struct {
89+ name string
90+ put func (context.Context , Blockstore , blocks.Block ) error
91+ }{
92+ {
93+ name : "Put" ,
94+ put : func (ctx context.Context , bs Blockstore , b blocks.Block ) error { return bs .Put (ctx , b ) },
95+ },
96+ {
97+ name : "PutMany" ,
98+ put : func (ctx context.Context , bs Blockstore , b blocks.Block ) error {
99+ return bs .PutMany (ctx , []blocks.Block {b })
100+ },
101+ },
102+ } {
103+ t .Run (tc .name , func (t * testing.T ) {
104+ ctx := context .Background ()
105+ rootstore := memory .NewDatastore (ctx )
106+
107+ blockNS := namespace .Wrap (rootstore , []byte {blockStoreKey })
108+ block := putMarkedBlock (t , ctx , blockNS , []byte ("merged then re-imported" ),
109+ newToMergeValue (time .Unix (1_700_000_000 , 0 )))
110+
111+ blockstore := BlockstoreFrom (rootstore , immutable .None [int ]())
112+ require .NoError (t , blockstore .MarkAsMerged (ctx , block .Cid ()))
113+ merged , err := blockstore .IsMerged (ctx , block .Cid ())
114+ require .NoError (t , err )
115+ require .True (t , merged )
116+
117+ require .NoError (t , tc .put (ctx , P2PBlockstoreFrom (rootstore , immutable .None [int ]()), block ))
118+
119+ merged , err = blockstore .IsMerged (ctx , block .Cid ())
120+ require .NoError (t , err )
121+ require .True (t , merged , "storing a block the node already holds must not unmerge it" )
122+ })
123+ }
124+ }
125+
83126func TestIsMerged_UnmergedAndAbsentBlocks (t * testing.T ) {
84127 ctx := context .Background ()
85128 rootstore := memory .NewDatastore (ctx )
0 commit comments