Skip to content

Commit

Permalink
Test and fix GC/pin bug #6252
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Erik Ingenito <erik.ingenito@protocol.ai>
  • Loading branch information
Erik Ingenito committed May 1, 2019
1 parent 0f53ad0 commit b6de9b1
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 7 deletions.
7 changes: 0 additions & 7 deletions core/coreunix/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ type Adder struct {
Silent bool
NoCopy bool
Chunker string
root ipld.Node
mroot *mfs.Root
unlocker bstore.Unlocker
tempRoot cid.Cid
Expand Down Expand Up @@ -132,11 +131,6 @@ func (adder *Adder) add(reader io.Reader) (ipld.Node, error) {

// RootNode returns the mfs root node
func (adder *Adder) curRootNode() (ipld.Node, error) {
// for memoizing
if adder.root != nil {
return adder.root, nil
}

mr, err := adder.mfsRoot()
if err != nil {
return nil, err
Expand All @@ -156,7 +150,6 @@ func (adder *Adder) curRootNode() (ipld.Node, error) {
root = nd
}

adder.root = root
return root, err
}

Expand Down
115 changes: 115 additions & 0 deletions core/coreunix/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,121 @@ import (

const testPeerID = "QmTFauExutTsy4XP6JbMFcw2Wa9645HJt2bTqL6qYDCKfe"

func TestAddMultipleGCLive(t *testing.T) {
r := &repo.Mock{
C: config.Config{
Identity: config.Identity{
PeerID: testPeerID, // required by offline node
},
},
D: syncds.MutexWrap(datastore.NewMapDatastore()),
}
node, err := core.NewNode(context.Background(), &core.BuildCfg{Repo: r})
if err != nil {
t.Fatal(err)
}

out := make(chan interface{}, 10)
adder, err := NewAdder(context.Background(), node.Pinning, node.Blockstore, node.DAG)
if err != nil {
t.Fatal(err)
}
adder.Out = out

// make two files with pipes so we can 'pause' the add for timing of the test
piper1, pipew1 := io.Pipe()
hangfile1 := files.NewReaderFile(piper1)

piper2, pipew2 := io.Pipe()
hangfile2 := files.NewReaderFile(piper2)

rfc := files.NewBytesFile([]byte("testfileA"))

slf := files.NewMapDirectory(map[string]files.Node{
"a": hangfile1,
"b": hangfile2,
"c": rfc,
})

addDone := make(chan struct{})
go func() {
defer close(addDone)
defer close(out)
_, _ = adder.AddAllAndPin(slf)

if err != nil {
t.Error(err)
}
}()

// Start writing the first file but don't close the stream
if _, err := pipew1.Write([]byte("some data for file a")); err != nil {
t.Fatal(err)
}

var gc1out <-chan gc.Result
gc1started := make(chan struct{})
go func() {
defer close(gc1started)
gc1out = gc.GC(context.Background(), node.Blockstore, node.Repo.Datastore(), node.Pinning, nil)
}()

// GC shouldn't get the lock until after the file is completely added
select {
case <-gc1started:
t.Fatal("gc shouldnt have started yet")
default:
}

// finish write and unblock gc
pipew1.Close()

// Should have gotten the lock at this point
<-gc1started

removedHashes := make(map[string]struct{})
for r := range gc1out {
if r.Error != nil {
t.Fatal(err)
}
removedHashes[r.KeyRemoved.String()] = struct{}{}
}

if _, err := pipew2.Write([]byte("some data for file b")); err != nil {
t.Fatal(err)
}

var gc2out <-chan gc.Result
gc2started := make(chan struct{})
go func() {
defer close(gc2started)
gc2out = gc.GC(context.Background(), node.Blockstore, node.Repo.Datastore(), node.Pinning, nil)
}()

select {
case <-gc2started:
t.Fatal("gc shouldnt have started yet")
default:
}

pipew2.Close()

<-gc2started

for r := range gc2out {
if r.Error != nil {
t.Fatal(err)
}
removedHashes[r.KeyRemoved.String()] = struct{}{}
}

for o := range out {
if _, ok := removedHashes[o.(*coreiface.AddEvent).Path.Cid().String()]; ok {
t.Fatal("gc'ed a hash we just added")
}
}
}

func TestAddGCLive(t *testing.T) {
r := &repo.Mock{
C: config.Config{
Expand Down

0 comments on commit b6de9b1

Please sign in to comment.