mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-30 18:13:54 +08:00
add test and locking fix
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
This commit is contained in:
15
mfs/dir.go
15
mfs/dir.go
@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ func NewDirectory(ctx context.Context, name string, node *dag.Node, parent child
|
|||||||
}
|
}
|
||||||
|
|
||||||
// closeChild updates the child by the given name to the dag node 'nd'
|
// closeChild updates the child by the given name to the dag node 'nd'
|
||||||
// and changes its own dag node, then propogates the changes upward
|
// and changes its own dag node
|
||||||
func (d *Directory) closeChild(name string, nd *dag.Node) error {
|
func (d *Directory) closeChild(name string, nd *dag.Node) error {
|
||||||
mynd, err := d.closeChildUpdate(name, nd)
|
mynd, err := d.closeChildUpdate(name, nd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -300,7 +301,7 @@ func (d *Directory) Unlink(name string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.parent.closeChild(d.name, d.node)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Directory) Flush() error {
|
func (d *Directory) Flush() error {
|
||||||
@ -375,6 +376,16 @@ func (d *Directory) sync() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Directory) Path() string {
|
||||||
|
cur := d
|
||||||
|
var out string
|
||||||
|
for cur != nil {
|
||||||
|
out = path.Join(cur.name, out)
|
||||||
|
cur = cur.parent.(*Directory)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Directory) GetNode() (*dag.Node, error) {
|
func (d *Directory) GetNode() (*dag.Node, error) {
|
||||||
d.lock.Lock()
|
d.lock.Lock()
|
||||||
defer d.lock.Unlock()
|
defer d.lock.Unlock()
|
||||||
|
145
mfs/mfs_test.go
145
mfs/mfs_test.go
@ -6,10 +6,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
randbo "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/randbo"
|
||||||
ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore"
|
ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore"
|
||||||
dssync "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore/sync"
|
dssync "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore/sync"
|
||||||
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
|
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
|
||||||
@ -474,3 +476,146 @@ func TestMfsFile(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func randomWalk(d *Directory, n int) (*Directory, error) {
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
dirents, err := d.List()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var childdirs []NodeListing
|
||||||
|
for _, child := range dirents {
|
||||||
|
if child.Type == int(TDir) {
|
||||||
|
childdirs = append(childdirs, child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(childdirs) == 0 {
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
next := childdirs[rand.Intn(len(childdirs))].Name
|
||||||
|
|
||||||
|
nextD, err := d.Child(next)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d = nextD.(*Directory)
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomName() string {
|
||||||
|
set := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_"
|
||||||
|
length := rand.Intn(10) + 2
|
||||||
|
var out string
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
j := rand.Intn(len(set))
|
||||||
|
out += set[j : j+1]
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func actorMakeFile(d *Directory) error {
|
||||||
|
d, err := randomWalk(d, rand.Intn(7))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := randomName()
|
||||||
|
f, err := NewFile(name, &dag.Node{Data: ft.FilePBData(nil, 0)}, d, d.dserv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := io.LimitReader(randbo.New(), int64(77*rand.Intn(123)))
|
||||||
|
_, err = io.Copy(f, r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func actorMkdir(d *Directory) error {
|
||||||
|
d, err := randomWalk(d, rand.Intn(7))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = d.Mkdir(randomName())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func actorRemoveFile(d *Directory) error {
|
||||||
|
d, err := randomWalk(d, rand.Intn(7))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ents, err := d.List()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ents) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
re := ents[rand.Intn(len(ents))]
|
||||||
|
|
||||||
|
return d.Unlink(re.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testActor(rt *Root, iterations int, errs chan error) {
|
||||||
|
d := rt.GetValue().(*Directory)
|
||||||
|
for i := 0; i < iterations; i++ {
|
||||||
|
switch rand.Intn(4) {
|
||||||
|
case 0:
|
||||||
|
if err := actorMkdir(d); err != nil {
|
||||||
|
errs <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case 1, 2:
|
||||||
|
if err := actorMakeFile(d); err != nil {
|
||||||
|
errs <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if err := actorRemoveFile(d); err != nil {
|
||||||
|
errs <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errs <- nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMfsStress(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
_, rt := setupRoot(ctx, t)
|
||||||
|
|
||||||
|
numroutines := 2
|
||||||
|
|
||||||
|
errs := make(chan error)
|
||||||
|
for i := 0; i < numroutines; i++ {
|
||||||
|
go testActor(rt, 50, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < numroutines; i++ {
|
||||||
|
err := <-errs
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user