func testInsert(t *testing.T, e *Editor, path, data string, create bool, experr string) { child := dag.NodeWithData([]byte(data)) ck, err := e.tmp.Add(child) if err != nil { t.Fatal(err) } var c func() *dag.ProtoNode if create { c = func() *dag.ProtoNode { return &dag.ProtoNode{} } } err = e.InsertNodeAtPath(context.Background(), path, child, c) if experr != "" { var got string if err != nil { got = err.Error() } if got != experr { t.Fatalf("expected '%s' but got '%s'", experr, got) } return } if err != nil { t.Fatal(err, path, data, create, experr) } assertNodeAtPath(t, e.tmp, e.root, path, ck) }
func actorMakeFile(d *Directory) error { d, err := randomWalk(d, rand.Intn(7)) if err != nil { return err } name := randomName() f, err := NewFile(name, dag.NodeWithData(ft.FilePBData(nil, 0)), d, d.dserv) if err != nil { return err } wfd, err := f.Open(OpenWriteOnly, true) if err != nil { return err } rread := rand.New(rand.NewSource(time.Now().UnixNano())) r := io.LimitReader(rread, int64(77*rand.Intn(123))) _, err = io.Copy(wfd, r) if err != nil { return err } err = wfd.Close() if err != nil { return err } return nil }
func TestAddLink(t *testing.T) { ds := mdtest.Mock() fishnode := dag.NodeWithData([]byte("fishcakes!")) fk, err := ds.Add(fishnode) if err != nil { t.Fatal(err) } nd := new(dag.ProtoNode) nnode, err := addLink(context.Background(), ds, nd, "fish", fishnode) if err != nil { t.Fatal(err) } fnprime, err := nnode.GetLinkedNode(context.Background(), ds, "fish") if err != nil { t.Fatal(err) } fnpkey := fnprime.Cid() if !fnpkey.Equals(fk) { t.Fatal("wrong child node found!") } }
func newFan(t *testing.T, ds mdag.DAGService) node.Node { a := mdag.NodeWithData([]byte("/a")) addLink(t, ds, a, child(t, ds, a, "aa")) addLink(t, ds, a, child(t, ds, a, "ab")) addLink(t, ds, a, child(t, ds, a, "ac")) addLink(t, ds, a, child(t, ds, a, "ad")) return a }
// AddLink creates a unixfs symlink and returns its hash func (s *Shell) AddLink(target string) (string, error) { d, _ := ft.SymlinkData(target) nd := dag.NodeWithData(d) c, err := s.node.DAG.Add(nd) if err != nil { return "", err } return c.String(), nil }
func TestBadPBData(t *testing.T) { dserv := testu.GetDAGServ() ctx, closer := context.WithCancel(context.Background()) defer closer() node := mdag.NodeWithData([]byte{42}) _, err := NewDagReader(ctx, node, dserv) if err == nil { t.Fatal("excepted error, got nil") } }
func newLinkedList(t *testing.T, ds mdag.DAGService) node.Node { a := mdag.NodeWithData([]byte("/a")) aa := child(t, ds, a, "aa") aaa := child(t, ds, aa, "aaa") aaaa := child(t, ds, aaa, "aaaa") aaaaa := child(t, ds, aaaa, "aaaaa") addLink(t, ds, aaaa, aaaaa) addLink(t, ds, aaa, aaaa) addLink(t, ds, aa, aaa) addLink(t, ds, a, aa) return a }
func newBinaryTree(t *testing.T, ds mdag.DAGService) node.Node { a := mdag.NodeWithData([]byte("/a")) aa := child(t, ds, a, "aa") ab := child(t, ds, a, "ab") addLink(t, ds, aa, child(t, ds, aa, "aaa")) addLink(t, ds, aa, child(t, ds, aa, "aab")) addLink(t, ds, ab, child(t, ds, ab, "aba")) addLink(t, ds, ab, child(t, ds, ab, "abb")) addLink(t, ds, a, aa) addLink(t, ds, a, ab) return a }
func TestSet(t *testing.T) { ds := mdtest.Mock() limit := 10000 // 10000 reproduces the pinloss issue fairly reliably if os.Getenv("STRESS_IT_OUT_YO") != "" { limit = 10000000 } var inputs []*cid.Cid for i := 0; i < limit; i++ { c, err := ds.Add(dag.NodeWithData([]byte(fmt.Sprint(i)))) if err != nil { t.Fatal(err) } inputs = append(inputs, c) } out, err := storeSet(context.Background(), ds, inputs, ignoreCids) if err != nil { t.Fatal(err) } // weird wrapper node because loadSet expects us to pass an // object pointing to multiple named sets setroot := &dag.ProtoNode{} err = setroot.AddNodeLinkClean("foo", out) if err != nil { t.Fatal(err) } outset, err := loadSet(context.Background(), ds, setroot, "foo", ignoreCids) if err != nil { t.Fatal(err) } if len(outset) != limit { t.Fatal("got wrong number", len(outset), limit) } seen := cid.NewSet() for _, c := range outset { seen.Add(c) } for _, c := range inputs { if !seen.Has(c) { t.Fatalf("expected to have %s, didnt find it") } } }
func getFileHandle(r *mfs.Root, path string, create bool) (*mfs.File, error) { target, err := mfs.Lookup(r, path) switch err { case nil: fi, ok := target.(*mfs.File) if !ok { return nil, fmt.Errorf("%s was not a file", path) } return fi, nil case os.ErrNotExist: if !create { return nil, err } // if create is specified and the file doesnt exist, we create the file dirname, fname := gopath.Split(path) pdiri, err := mfs.Lookup(r, dirname) if err != nil { log.Error("lookupfail ", dirname) return nil, err } pdir, ok := pdiri.(*mfs.Directory) if !ok { return nil, fmt.Errorf("%s was not a directory", dirname) } nd := dag.NodeWithData(ft.FilePBData(nil, 0)) err = pdir.AddChild(fname, nd) if err != nil { return nil, err } fsn, err := pdir.Child(fname) if err != nil { return nil, err } fi, ok := fsn.(*mfs.File) if !ok { return nil, errors.New("Expected *mfs.File, didnt get it. This is likely a race condition.") } return fi, nil default: return nil, err } }
func (adder *Adder) addFile(file files.File) error { err := adder.maybePauseForGC() if err != nil { return err } if file.IsDirectory() { return adder.addDir(file) } // case for symlink if s, ok := file.(*files.Symlink); ok { sdata, err := unixfs.SymlinkData(s.Target) if err != nil { return err } dagnode := dag.NodeWithData(sdata) _, err = adder.dagService.Add(dagnode) if err != nil { return err } return adder.addNode(dagnode, s.FileName()) } // case for regular file // if the progress flag was specified, wrap the file so that we can send // progress updates to the client (over the output channel) var reader io.Reader = file if adder.Progress { rdr := &progressReader{file: file, out: adder.Out} if fi, ok := file.(files.FileInfo); ok { reader = &progressReader2{rdr, fi} } else { reader = rdr } } dagnode, err := adder.add(reader) if err != nil { return err } // patch it into the root return adder.addNode(dagnode, file.FileName()) }
func TestTypeFailures(t *testing.T) { dserv := testu.GetDAGServ() ctx, closer := context.WithCancel(context.Background()) defer closer() node := unixfs.EmptyDirNode() if _, err := NewDagReader(ctx, node, dserv); err != ErrIsDir { t.Fatalf("excepted to get %v, got %v", ErrIsDir, err) } data, err := unixfs.SymlinkData("/somelink") if err != nil { t.Fatal(err) } node = mdag.NodeWithData(data) if _, err := NewDagReader(ctx, node, dserv); err != ErrCantReadSymlinks { t.Fatalf("excepted to get %v, got %v", ErrCantReadSymlinks, err) } }
func (dir *Directory) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fs.Node, fs.Handle, error) { // New 'empty' file nd := dag.NodeWithData(ft.FilePBData(nil, 0)) err := dir.dir.AddChild(req.Name, nd) if err != nil { return nil, nil, err } child, err := dir.dir.Child(req.Name) if err != nil { return nil, nil, err } fi, ok := child.(*mfs.File) if !ok { return nil, nil, errors.New("child creation failed") } nodechild := &FileNode{fi: fi} var openflag int switch { case req.Flags.IsReadOnly(): openflag = mfs.OpenReadOnly case req.Flags.IsWriteOnly(): openflag = mfs.OpenWriteOnly case req.Flags.IsReadWrite(): openflag = mfs.OpenReadWrite default: return nil, nil, errors.New("unsupported open mode") } fd, err := fi.Open(openflag, true) if err != nil { return nil, nil, err } return nodechild, &File{fi: fd}, nil }
func TestMetadataNode(t *testing.T) { dserv := testu.GetDAGServ() rdata, rnode := testu.GetRandomNode(t, dserv, 512) _, err := dserv.Add(rnode) if err != nil { t.Fatal(err) } ctx, closer := context.WithCancel(context.Background()) defer closer() data, err := unixfs.BytesForMetadata(&unixfs.Metadata{"text", 125}) if err != nil { t.Fatal(err) } node := mdag.NodeWithData(data) _, err = NewDagReader(ctx, node, dserv) if err == nil { t.Fatal("expected an error") } if !strings.Contains(err.Error(), "incorrectly formatted") { t.Fatal("expected different error") } node.AddNodeLink("", rnode) reader, err := NewDagReader(ctx, node, dserv) if err != nil { t.Fatal(err) } readdata, err := ioutil.ReadAll(reader) if err != nil { t.Fatal(err) } if err := testu.ArrComp(rdata, readdata); err != nil { t.Fatal(err) } }
//TODO: hrm, maybe this interface could be better func (s *Shell) PatchLink(root, npath, childhash string, create bool) (string, error) { p, err := path.ParsePath(root) if err != nil { return "", err } rootnd, err := core.Resolve(s.ctx, s.node, p) if err != nil { return "", err } childpath, err := path.ParsePath(childhash) if err != nil { return "", err } nnode, err := core.Resolve(s.ctx, s.node, childpath) if err != nil { return "", err } e := dagutils.NewDagEditor(rootnd, s.node.DAG) err = e.InsertNodeAtPath(s.ctx, npath, nnode, func() *dag.Node { return dag.NodeWithData(ft.FolderPBData()) }) if err != nil { return "", err } _, err = e.Finalize(s.node.DAG) if err != nil { return "", err } return e.GetNode().Key().B58String(), nil }
func child(t *testing.T, ds mdag.DAGService, a node.Node, name string) node.Node { return mdag.NodeWithData([]byte(string(a.(*mdag.ProtoNode).Data()) + "/" + name)) }
func emptyDirNode() *dag.Node { return dag.NodeWithData(ft.FolderPBData()) }
func TestFlushing(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() _, rt := setupRoot(ctx, t) dir := rt.GetValue().(*Directory) c := mkdirP(t, dir, "a/b/c") d := mkdirP(t, dir, "a/b/d") e := mkdirP(t, dir, "a/b/e") data := []byte("this is a test\n") nd1 := dag.NodeWithData(ft.FilePBData(data, uint64(len(data)))) if err := c.AddChild("TEST", nd1); err != nil { t.Fatal(err) } if err := d.AddChild("TEST", nd1); err != nil { t.Fatal(err) } if err := e.AddChild("TEST", nd1); err != nil { t.Fatal(err) } if err := dir.AddChild("FILE", nd1); err != nil { t.Fatal(err) } if err := FlushPath(rt, "/a/b/c/TEST"); err != nil { t.Fatal(err) } if err := FlushPath(rt, "/a/b/d/TEST"); err != nil { t.Fatal(err) } if err := FlushPath(rt, "/a/b/e/TEST"); err != nil { t.Fatal(err) } if err := FlushPath(rt, "/FILE"); err != nil { t.Fatal(err) } rnd, err := dir.GetNode() if err != nil { t.Fatal(err) } pbrnd, ok := rnd.(*dag.ProtoNode) if !ok { t.Fatal(dag.ErrNotProtobuf) } fsnode, err := ft.FSNodeFromBytes(pbrnd.Data()) if err != nil { t.Fatal(err) } if fsnode.Type != ft.TDirectory { t.Fatal("root wasnt a directory") } rnk := rnd.Cid() exp := "QmWMVyhTuyxUrXX3ynz171jq76yY3PktfY9Bxiph7b9ikr" if rnk.String() != exp { t.Fatalf("dag looks wrong, expected %s, but got %s", exp, rnk.String()) } }
func TestFileDescriptors(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ds, rt := setupRoot(ctx, t) dir := rt.GetValue().(*Directory) nd := dag.NodeWithData(ft.FilePBData(nil, 0)) fi, err := NewFile("test", nd, dir, ds) if err != nil { t.Fatal(err) } // test read only rfd1, err := fi.Open(OpenReadOnly, false) if err != nil { t.Fatal(err) } err = rfd1.Truncate(0) if err == nil { t.Fatal("shouldnt be able to truncate readonly fd") } _, err = rfd1.Write([]byte{}) if err == nil { t.Fatal("shouldnt be able to write to readonly fd") } _, err = rfd1.Read([]byte{}) if err != nil { t.Fatalf("expected to be able to read from file: %s", err) } done := make(chan struct{}) go func() { defer close(done) // can open second readonly file descriptor rfd2, err := fi.Open(OpenReadOnly, false) if err != nil { t.Error(err) return } rfd2.Close() }() select { case <-time.After(time.Second): t.Fatal("open second file descriptor failed") case <-done: } if t.Failed() { return } // test not being able to open for write until reader are closed done = make(chan struct{}) go func() { defer close(done) wfd1, err := fi.Open(OpenWriteOnly, true) if err != nil { t.Error(err) } wfd1.Close() }() select { case <-time.After(time.Millisecond * 200): case <-done: if t.Failed() { return } t.Fatal("shouldnt have been able to open file for writing") } err = rfd1.Close() if err != nil { t.Fatal(err) } select { case <-time.After(time.Second): t.Fatal("should have been able to open write fd after closing read fd") case <-done: } wfd, err := fi.Open(OpenWriteOnly, true) if err != nil { t.Fatal(err) } _, err = wfd.Read([]byte{}) if err == nil { t.Fatal("shouldnt have been able to read from write only filedescriptor") } _, err = wfd.Write([]byte{}) if err != nil { t.Fatal(err) } }
func EmptyDirNode() *dag.ProtoNode { return dag.NodeWithData(FolderPBData()) }
func child(t *testing.T, ds mdag.DAGService, a *mdag.Node, name string) *mdag.Node { return mdag.NodeWithData([]byte(string(a.Data()) + "/" + name)) }