コード例 #1
0
ファイル: mdfs_test.go プロジェクト: Christopheraburns/clive
func testfn(t *testing.T, fns ...func(t fstest.Fataler, fss ...zx.Tree)) {
	bufs.Size = 1 * 1024
	os.RemoveAll(tlfsdir)
	defer os.RemoveAll(tlfsdir)
	if err := os.Mkdir(tlfsdir, 0755); err != nil {
		t.Fatalf("lfs: %s", err)
	}
	os.Args[0] = "mdfs_test"
	dfs, err := lfs.New("	cache", tlfsdir, lfs.RW)
	if err != nil {
		t.Fatalf("lfs: %s", err)
	}
	dfs.SaveAttrs(true)
	mfs, err := New("example mfs", dfs)
	if err != nil {
		t.Fatalf("lfs: %s", err)
	}
	xfs, _ := mfs.AuthFor(&auth.Info{Uid: dbg.Usr, SpeaksFor: dbg.Usr, Ok: true})
	fs := xfs.(zx.RWTree)
	fstest.MkZXTree(t, fs)
	mfs.Dbg = testing.Verbose()
	dfs.Dbg = testing.Verbose()
	var fn func(t fstest.Fataler, fss ...zx.Tree)
	if len(fns) > 0 {
		fn = fns[0]
	}
	if fn != nil {
		if mfs.Dbg {
			defer func() {
				mfs.Dump(os.Stdout)
				dfs.Dump(os.Stdout)
			}()
		}
		for _, fn := range fns {
			fn(t, fs)
		}
	} else {
		d1, _ := zx.Stat(mfs, "/")
		printf("mfs st:\t%s\n", d1)
		d1, _ = zx.Stat(dfs, "/")
		printf("lfs st:\t%s\n", d1)
		// recreate, to test a reload
		mfs, err = New("example mfs", dfs)
		if err != nil {
			t.Fatalf("lfs: %s", err)
		}
		mfs.Dbg = testing.Verbose()
		xfs, _ = mfs.AuthFor(&auth.Info{Uid: dbg.Usr, SpeaksFor: dbg.Usr, Ok: true})
		fs = xfs.(zx.RWTree)
		if mfs.Dbg {
			defer func() {
				mfs.Dump(os.Stdout)
				dfs.Dump(os.Stdout)
			}()
		}
	}
	mfs.Dbg = false
	dfs.Dbg = false
	fstest.SameDump(t, mfs, dfs)
}
コード例 #2
0
ファイル: fstest.go プロジェクト: Christopheraburns/clive
func Moves(t Fataler, fss ...zx.Tree) {
	fs := fss[0].(zx.RWTree)
	for _, mv := range MoveTests {
		printf("mv %s %s\n", mv.From, mv.To)
		err := <-fs.Move(mv.From, mv.To)
		if mv.Fails {
			if err==nil {
				t.Fatalf("mv %s didn't fail", mv.From)
			}
			continue
		}
		if err != nil {
			t.Fatalf("mv %s: %s", mv.From, err)
		}
		d, err := zx.Stat(fs, mv.To)
		if err != nil {
			t.Fatalf("stat %s: %s", mv.From, err)
		}
		delete(d, "Sum")
		r := d.LongTestFmt()
		printf("new stat: %s\n", r)
		if strings.Contains(mv.Res, "size X") {	// as is, with ctl, with ctl and chg
			r = strings.Replace(r, "size 5", "size X", 1)
			r = strings.Replace(r, "size 6", "size X", 1)
			r = strings.Replace(r, "size 7", "size X", 1)
		}
		r = strings.Replace(r, dbg.Usr, "nemo", -1)
		if mv.Res != "" && !strings.HasPrefix(r, mv.Res) {
			t.Fatalf("bad new stat %s", r)
		}
		if mv.Child != "" {
			d, err = zx.Stat(fs, mv.Child)
			if err != nil {
				t.Fatalf("stat %s: %s", mv.Child, err)
			}
			if d["path"] != mv.Child {
				t.Fatalf("%s: bad path %s", mv.Child, d["path"])
			}
		}
		paths := []string{mv.From, mv.To, path.Dir(mv.From), path.Dir(mv.To)}
		for _, p := range paths {
			d, err := zx.Stat(fs, mv.To)
			if err != nil {
				t.Fatalf("stat %s: %s", p, err)
			}
			chkdirs(t, fs, d, false)
		}
	}
	printf("\n")
}
コード例 #3
0
ファイル: sync.go プロジェクト: Christopheraburns/clive
func (c *FileInfo) syncData() {
	d, err := zx.Stat(c.lfs, c.path)
	if err != nil {
		c.dprintf("sync %s: %s\n", c.path, err)
		c.invalid()
		return
	}
	if c.wasdel {
		if c.path == "" || c.path == "/" {
			panic("remove all /")
		}
		<-c.rfs.RemoveAll(c.path) // and ignore errors
	}
	delete(d, "Rtime")
	delete(d, "Cache")
	d["Mode"] = d["mode"]
	if d["type"] == "d" {
		err = <-c.rfs.Mkdir(c.path, d)
	} else {
		datc := c.lfs.Get(c.path, 0, zx.All, "")
		rc := c.rfs.Put(c.path, d, 0, datc, "")
		<-rc
		err = cerror(rc)
	}
	c.state = CClean
	if err != nil {
		c.dprintf("%s: sync meta: %s\n", c.path, err)
		c.invalid()
	}
	c.wasdel = false
}
コード例 #4
0
ファイル: perms.go プロジェクト: Christopheraburns/clive
func authfs(t Fataler, xfs zx.Tree) zx.RWTree {
	d, err := zx.Stat(xfs, "/d")
	if err != nil {
		t.Fatalf("stat: %s", err)
	}
	printf("d is: %s\n", d)
	uid := d["Uid"]
	if uid == "" {
		t.Fatalf("no uid")
	}
	gid := d["Gid"]
	if uid == "" {
		t.Fatalf("no gid")
	}
	wuid := d["Wuid"]
	if wuid == "" {
		t.Fatalf("no wuid")
	}
	ai := &auth.Info{
		Uid: uid, SpeaksFor: uid, Ok: true,
		Gids: map[string]bool{"gid1": true, "gid2": true},
	}
	if gid != uid {
		ai.Gids[gid] = true
	}
	return authfor(t, xfs, ai)
}
コード例 #5
0
ファイル: nspace.go プロジェクト: Christopheraburns/clive
// If ln is "path addr" and addr is of the form
// net ! addr ! proto ! tree ! path
// or
// /one/path
// the dial the tree and walk to the path.
func specialForm(ln string) (string, zx.Dir) {
	if len(ln)==0 || ln[0]!='/' {
		return "", nil
	}
	toks := strings.Fields(ln)
	if len(toks)!=2 || len(toks[0])==0 || len(toks[1])==0 {
		return "", nil
	}
	p, addr := toks[0], toks[1]
	if addr[0] == '/' {
		addr = "*!*!lfs!main!" + addr
	}
	atoks := strings.SplitN(addr, "!", -1)
	if len(atoks) < 2 {
		return "", nil
	}
	t, err := rfs.Import(addr)
	if err != nil {
		dbg.Warn("ns: %s: import: %s", ln, err)
		return "", nil
	}
	path := "/"
	if len(atoks)>=5 && atoks[2]!="lfs" {
		path = atoks[4]
	}
	d, err := zx.Stat(t, path)
	if err != nil {
		dbg.Warn("ns: %s: stat: %s", ln, err)
		return "", nil
	}
	return p, d
}
コード例 #6
0
ファイル: perms.go プロジェクト: Christopheraburns/clive
func nostat(t Fataler, fs zx.Tree, p string) bool {
	_, err := zx.Stat(fs, p)
	if err == nil {
		t.Logf("could stat %s", p)
		return false
	}
	return true
}
コード例 #7
0
ファイル: pred.go プロジェクト: Christopheraburns/clive
/*
	Execute the part of the ns.Find operation that evaluates p
	at the tree rooted at d (considering that its level is the one
	indicated). Found entries are sent through the given channel,
	which is closed only upon errors.

	This is useful to implement ns.Find when writting services.
*/
func (p *Pred) FindAt(fs zx.Sender, d zx.Dir, c chan<- zx.Dir, lvl int) {
	match, pruned, err := p.EvalAt(d, lvl)
	if err != nil {
		close(c, err)
		return
	}
	if pruned {
		nd := d.Dup()
		nd["err"] = "pruned"
		c <- nd
		return
	}
	if d["rm"] != "" {
		return
	}
	var ds []zx.Dir
	if d["type"] == "d" {
		ds, err = zx.GetDir(fs, d["path"])
	}
	if err != nil {
		nd := d.Dup()
		nd["err"] = err.Error()
		c <- nd
		return
	}
	if match {
		if ok := c <- d; !ok {
			return
		}
	}
	for i := 0; i < len(ds); i++ {
		cd := ds[i]
		if cd["rm"] != "" {
			continue
		}
		p.FindAt(fs, cd, c, lvl+1)
	}
}

func Find(fs zx.Tree, path, pred string) <-chan zx.Dir {
	c := make(chan zx.Dir)
	go func() {
		d, err := zx.Stat(fs, path)
		if d == nil {
			close(c, err)
			return
		}
		x, err := New(pred)
		if err != nil {
			close(c, err)
			return
		}
		x.FindAt(fs, d, c, 0)
		close(c)
	}()
	return c
}
コード例 #8
0
ファイル: fstest.go プロジェクト: Christopheraburns/clive
func DirSizes(t Fataler, fss ...zx.Tree) {
	for _, fs := range fss {
		rf, err := zx.Stat(fs, "/")
		if err != nil {
			t.Fatalf("stat: %s", err)
		}
		chkdirs(t, fs, rf, true)
	}
}
コード例 #9
0
ファイル: stats.go プロジェクト: chengguozhen/clive
func Stats(t Fataler, fs zx.Fs) {
	ds := []zx.Dir{}
	for _, p := range AllFiles {
		dc := fs.Stat(p)
		d := <-dc
		if err := cerror(dc); err != nil {
			t.Fatalf("stat %s: %s", p, err)
		}
		ds = append(ds, d)
	}

	for _, d := range ds {
		Printf("%s\n", d.Fmt())
	}
	Printf("\n")
	for _, d := range ds {
		Printf("%s\n", d.LongFmt())
	}
	Printf("\n")
	for i, d := range ds {
		s := d.TestFmt()
		Printf("`%s`,\n", s)
		if s != stats[i] && !strings.HasPrefix(s, stats[i]) {
			Printf("not `%s`,\n", stats[i])
			t.Fatalf("bad stat")
		}
	}
	Printf("\n")

	for _, p := range NotThere {
		dc := fs.Stat(p)
		d := <-dc
		if d != nil {
			t.Fatalf("%s is there", p)
		}
		if !zx.IsNotExist(cerror(dc)) {
			Printf("bad err %v\n", cerror(dc))
		}
	}

	for i, p := range BadPaths {
		d, err := zx.Stat(fs, p)
		if d != nil {
			Printf("%s\n", d.TestFmt())
		} else {
			Printf("err %s\n", err)
		}
		if i == 0 && d["path"] != "/" {
			t.Fatalf("bad bad path")
		}
		if i > 0 && d != nil {
			t.Fatalf("bad bad path")
		}
	}
}
コード例 #10
0
ファイル: ns_test.go プロジェクト: Christopheraburns/clive
func mkns(t *testing.T, d bool) *Tree {
	lfs1, lfs2 := mktrees(t)

	ns := New()
	ns.Debug = d
	ns.DebugFind = d

	root1, err := zx.Stat(lfs1, "/")
	if err != nil {
		t.Fatalf("stat: %s", err)
	}
	err = <-ns.Mount("/", root1, Repl)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}

	root2, err := zx.Stat(lfs2, "/")
	if err != nil {
		t.Fatalf("stat: %s", err)
	}
	err = <-ns.Mount("/a/b", root2, Repl)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	d1 := zx.Dir{"path": "x", "name": "x", "proto": "p1"}
	err = <-ns.Mount("/d", d1, Before)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	d2 := zx.Dir{"path": "x", "name": "x", "proto": "p2"}
	err = <-ns.Mount("/d", d2, After)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	err = <-ns.Mount("/d", d2, After)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	printf("ns is `%s`\n", ns)
	return ns
}
コード例 #11
0
ファイル: fscmp.go プロジェクト: fjballest/clive
// Compute changes for fs1 to become like fs2 and send them through the
// returned chan.
// If no path is given, "/" is used.
func Diff(fs1, fs2 zx.Getter, path ...string) <-chan zx.Chg {
	p := "/"
	if len(path) > 0 {
		p = path[0]
	}
	rc := make(chan zx.Chg)
	// TODO: this should use find instead of stat+get
	go func() {
		var d1, d2 zx.Dir
		var err error
		d1, err = zx.Stat(fs1, p)
		if err == nil {
			d2, err = zx.Stat(fs2, p)
		}
		if err == nil {
			err = diff(d1, d2, fs1, fs2, rc)
		}
		close(rc, err)
	}()
	return rc
}
コード例 #12
0
ファイル: mdfs.go プロジェクト: Christopheraburns/clive
// no locks, used only at init time
func (t *Fs) reload() {
	d, err := zx.Stat(t.lfs, "/")
	if err != nil {
		dbg.Warn("%s: reload: %s", t.name, err)
		return
	}
	ud := d.UsrAttrs()
	ud["Sum"] = d["Sum"]
	for k, v := range ud {
		t.root.d[k] = v
	}
	t.reloadChild(t.root)
}
コード例 #13
0
ファイル: ns_test.go プロジェクト: Christopheraburns/clive
func mkmfstrees(t *testing.T) (zx.RWTree, zx.RWTree) {
	lfs1, err := mfs.New(tdir)
	if err != nil {
		t.Fatalf("mfs: %s", err)
	}
	fstest.MkZXTree(t, lfs1)
	d, err := zx.Stat(lfs1, "/")
	if err != nil {
		t.Fatalf("mfs: %s", err)
	}
	zx.RegisterProcTree(lfs1, d["tpath"])
	lfs1.Dbg = testing.Verbose() && moreverb
	return lfs1, lfs1
}
コード例 #14
0
ファイル: filetest.go プロジェクト: Christopheraburns/clive
func (tf *File) Seek(off int64, whence int) (int64, error) {
	switch whence {
	case 0:
		tf.off = off
	case 1:
		tf.off += off
	case 2:
		st, err := zx.Stat(tf.t, tf.path)
		if err != nil {
			return 0, err
		}
		tf.off = st.Int64("size") + off
	}
	return tf.off, nil
}
コード例 #15
0
ファイル: cfs.go プロジェクト: Christopheraburns/clive
func chkok(fs zx.Tree, attr string) error {
	d, err := zx.Stat(fs, "/")
	if err != nil  {
		return fmt.Errorf("%s: %s", fs.Name(), err)
	}
	rwfs, ok := fs.(zx.RWTree)
	if !ok {
		return nil
	}
	if err := <-rwfs.Wstat("/", zx.Dir{attr: "666"}); err != nil {
		return err
	}
	d, err = zx.Stat(fs, "/")
	if err != nil  {
		return fmt.Errorf("%s: %s", fs.Name(), err)
	}
	if d[attr] != "666" {
		return fmt.Errorf("%s: does not preserve %s", fs.Name(), attr)
	}
	if err := <-rwfs.Wstat("/", zx.Dir{attr: ""}); err != nil {
		return err
	}
	return nil
}
コード例 #16
0
ファイル: nsutil.go プロジェクト: Christopheraburns/clive
// zx.Stat using the app ns and dot.
func Stat(path string) (zx.Dir, error) {
	if len(path) > 0 && path[0] == '#' {
		_, err := app.IOarg(path)
		if err != nil {
			return nil, fmt.Errorf("%s: %s", path, err)
		}
		d := zx.Dir{"path": path, "name": path,
			"upath": path, "type":"c"}
		return d, nil
	}
	path = app.AbsPath(path)
	_, trs, spaths, err := app.ResolveTree(path)
	if err != nil {
		return nil, err
	}
	return zx.Stat(trs[0], spaths[0])
}
コード例 #17
0
ファイル: zxc_test.go プロジェクト: chengguozhen/clive
func runTest(t *testing.T, fn fstest.TestFunc) {
	os.Args[0] = "rzx.test"
	fstest.Verb = testing.Verbose()
	ccfg, err := net.TLSCfg("/Users/nemo/.ssh/client")
	if err != nil {
		t.Logf("no certs found, no tls conn")
	}
	scfg, err := net.TLSCfg("/Users/nemo/.ssh/server")
	if err != nil || ccfg == nil {
		ccfg = nil
		scfg = nil
		t.Logf("no certs found, no tls conn")
	}
	_, _ = scfg, ccfg
	fstest.MkTree(t, tdir)
	defer os.RemoveAll(tdir)
	lfs, err := zux.NewZX(tdir)
	if err != nil {
		t.Fatal(err)
	}
	defer lfs.Sync()

	cfs, err := New(lfs)
	if err != nil {
		t.Fatal(err)
	}
	defer cfs.Close()
	cfs.Debug = testing.Verbose()
	lfs.Debug = testing.Verbose()
	cfs.Flags.Set("rfsdebug", cfs.Debug)
	cfs.Flags.Set("cachedebug", cfs.Debug)
	if fn != nil {
		fn(t, cfs)
	} else {
		d, err := zx.Stat(cfs, "/")
		if err != nil {
			t.Fatalf("stat /: %v", err)
		}
		t.Logf("/ stat is %s\n", d.TestFmt())
	}
	if cfs.Debug {
		cfs.c.dump()
	}
}
コード例 #18
0
ファイル: fstest.go プロジェクト: Christopheraburns/clive
func EqFiles(t Fataler, path string, fss ...zx.Tree) {
	dirs := []zx.Dir{}
	nerrs := 0
	for _, fs := range fss {
		d, err := zx.Stat(fs, path)
		if err != nil {
			printf("%s: not there: %s\n", fs.Name(), err)
			nerrs++
			continue
		}
		printf("%s: %s\n", fs.Name(), d.LongTestFmt())
		dirs = append(dirs, d)
	}
	if nerrs > 0 {
		if nerrs != len(fss) {
			t.Fatalf("exists only in some")
		}
		return
	}
	for i := 1; i < len(dirs); i++ {
		if dirs[i].TestFmt() != dirs[0].TestFmt() {
			t.Logf("dir%d %s\n", i, dirs[i].TestFmt())
			t.Logf("dir0 %s\n", dirs[0].TestFmt())
			t.Fatalf("dirs do not match")
		}
	}
	if dirs[0]["type"] == "d" {
		return
	}
	datas := [][]byte{}
	for _, fs := range fss {
		dat, err := zx.GetAll(fs, path)
		if err != nil {
			t.Fatalf("%s: %s: %s", fs, path, err)
		}
		datas = append(datas, dat)
	}
	for i := 1; i < len(datas); i++ {
		if bytes.Compare(datas[i], datas[0]) != 0 {
			t.Fatalf("data differs")
		}
	}

}
コード例 #19
0
ファイル: sync.go プロジェクト: Christopheraburns/clive
func (c *FileInfo) syncMeta() {
	d, err := zx.Stat(c.lfs, c.path)
	if err == nil {
		d = d.UsrAttrs()
		delete(d, "mtime")
		delete(d, "size")
		delete(d, "Rtime")
		delete(d, "Cache")
		d["Mode"] = d["mode"]
		err = <-c.rfs.Wstat(c.path, d)
	}
	if err != nil {
		c.dprintf("%s: sync meta: %s\n", c.path, err)
		c.invalid()
	} else if c.state == CUnreadMeta {
		c.state = CUnread
	} else {
		c.state = CClean
	}
	c.wasdel = false
}
コード例 #20
0
ファイル: perms.go プロジェクト: Christopheraburns/clive
func stat(t Fataler, fs zx.Tree, p, res string) bool {
	d, err := zx.Stat(fs, p)
	if err != nil {
		t.Fatalf("stat: %s", err)
	}
	s := fmt.Sprintf("%s %s %s %s", d["mode"], d["Uid"], d["Gid"], d["Wuid"])
	us := strings.Replace(s, dbg.Usr, "nemo", -1)
	printf("%s: %s\n", p, us)

	// At least lfs does not update Wuid for directories, but that's ok
	if d["type"] == "d" && res != "" {
		toks := strings.Fields(res)
		res = strings.Join(toks[:len(toks)-1], " ")
		s = fmt.Sprintf("%s %s %s", d["mode"], d["Uid"], d["Gid"])
		us = strings.Replace(s, dbg.Usr, "nemo", -1)
	}
	if res != "" && us != res {
		t.Logf("wrong stat for %s <%s>", p, us)
		return false
	}
	return true
}
コード例 #21
0
ファイル: val.go プロジェクト: Christopheraburns/clive
func attr(aname string, v1 value) (value, error) {
	fname, ok := v1.(string)
	if !ok {
		return nil, errors.New("not a file name")
	}
	fname, _ = filepath.Abs(fname)
	_, ts, ns, err := cmd.ResolveTree(fname)
	if err != nil {
		panic(err)
	}
	t := ts[0]
	spath := ns[0]
	d, err := zx.Stat(t, spath)
	if err != nil {
		panic(err)
	}
	if aname == "r" {
		return d.Int("mode")&0444 != 0, nil
	}
	if aname == "w" {
		return d.Int("mode")&0222 != 0, nil
	}
	if aname == "x" {
		return d.Int("mode")&0111 != 0, nil
	}
	if aname == "mode" {
		return fmt.Sprintf("0%o", d.Int("mode")&0777), nil
	}
	if aname == "size" {
		return uint64(d.Int64("size")), nil
	}
	if aname == "mtime" {
		return d.Time("mtime"), nil
	}
	return d[aname], nil
}
コード例 #22
0
ファイル: ns_test.go プロジェクト: Christopheraburns/clive
func mkrns(t *testing.T, d bool) *Tree {
	fstest.MkTree(t, tdir)
	lfs1, err := lfs.New(tdir, tdir, lfs.RW)
	if err != nil {
		t.Fatalf("lfs: %s", err)
	}
	hs, hc := fifo.NewChanHandler()
	s := fifo.New("rfs", "rfs", hs)
	if err = s.Serve(); err != nil {
		t.Fatalf("%s", err)
	}
	go func() {
		for c := range hc {
			ai, err := auth.AtServer(*c, "", "zx", "finder")
			if err!=nil && err!=auth.ErrDisabled {
				dbg.Warn("auth %s: %s\n", c.Tag, err)
				close(c.In, err)
				close(c.Out, err)
				return
			}
			rfs.Serve("srv", *c, ai, rfs.RW, lfs1)
		}
	}()
	rfs1, err := rfs.Import("fifo!*!rfs")
	if err != nil {
		t.Fatalf("lfs: %s", err)
	}
	ns := New()

	ns.Debug = d
	ns.DebugFind = d

	root1, err := zx.Stat(lfs1, "/")
	if err != nil {
		t.Fatalf("stat: %s", err)
	}
	err = <-ns.Mount("/", root1, Repl)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}

	root2, err := zx.Stat(rfs1, "/")
	if err != nil {
		t.Fatalf("stat: %s", err)
	}
	err = <-ns.Mount("/a/b", root2, Repl)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	d1 := zx.Dir{"path": "x", "name": "x", "proto": "p1"}
	err = <-ns.Mount("/d", d1, Before)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	d2 := zx.Dir{"path": "x", "name": "x", "proto": "p2"}
	err = <-ns.Mount("/d", d2, After)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	err = <-ns.Mount("/d", d2, After)
	if err != nil {
		t.Fatalf("mount: %s", err)
	}
	printf("ns is `%s`\n", ns)
	return ns
}
コード例 #23
0
ファイル: fstest.go プロジェクト: Christopheraburns/clive
func Puts(t Fataler, fss ...zx.Tree) {
	if len(fss) == 0 {
		t.Fatalf("no fs given")
	}
	fs := fss[0].(zx.RWTree)
	rd, err := zx.Stat(fs, "/")
	if err != nil {
		t.Fatalf("root stat %s", err)
	}
	printf("root %s\n", rd.TestFmt())
	for z := 0; z < Repeats; z++ {
	Loop:
		for nfi, nf := range PutTests {
			dc := make(chan []byte, 1)
			nf.data = make([]byte, 0, 32*1024)
			xd := nf.Dir.Dup()
			printf("put %s %v\n", nf.Path, xd)
			nn := nfi + 1
			if nf.N != 0 {
				nn = 2
			}
			xc := fs.Put(nf.Path, xd, 0, dc, "")
			for i := 0; i < 1000*nn; i++ {
				msg := []byte(fmt.Sprintf("hi %s %d\n", nf.Path, i))
				nf.data = append(nf.data, msg...)
				if ok := dc <- msg; !ok {
					err := cerror(dc)
					if !nf.Fails {
						t.Fatalf("%s: %s\n", nf.Path, err)
					}
					continue Loop
				}
			}
			printf("put %s: sent %d bytes\n", nf.Path, len(nf.data))
			close(dc)
			xd = <-xc
			if nf.Fails {
				if xd!=nil || cerror(xc)==nil {
					t.Fatalf("%s: didn't fail", nf.Path)
				}
				continue
			}
			if xd==nil || cerror(xc)!=nil {
				t.Fatalf("%s: %s\n", nf.Path, cerror(xc))
			}
			got := xd.TestFmt()
			printf("got %s\n", got)
			if nf.Dir["mtime"] != "" {
				got += " mtime " + xd["mtime"]
			}
			if got != nf.Res {
				t.Logf("expected %s\n", nf.Res)
				t.Logf("got %s\n", got)
				t.Fatalf("%s: bad dir output", nf.Path)
			}
			fd, err := zx.Stat(fs, nf.Path)
			if err != nil {
				t.Fatalf("stat: %s", err)
			}
			got = fd.TestFmt()
			if nf.Dir["mtime"] != "" {
				got += " mtime " + fd["mtime"]
			}
			if nf.Dir["X"] != "" {
				got += " X " + fd["X"]
			}
			printf("after put: %s\n", got)
			if nf.Rdir != "" && nf.Rdir != got {
				t.Logf("expected <%s>", nf.Rdir)
				t.Fatalf("got <%s>", got)
			}
			for _, fs := range fss {
				dat, err := zx.GetAll(fs, nf.Path)
				if err != nil {
					t.Fatalf("couldn't get: %s", err)
				}
				if nf.N != 0 && len(dat) != nf.N {
					t.Fatalf("bad output size: %d", len(dat))
				}
				if nf.N != 0 && len(dat) > len(nf.data) {
					dat = dat[:len(nf.data)]
				}
				if nf.N != 0 && len(dat) < len(nf.data) {
					nf.data = nf.data[:len(dat)]
				}
				if string(dat) != string(nf.data) {
					t.Fatalf("bad data %d vs %d bytes", len(dat), len(nf.data))
				}
			}
		}
	}
}


func GetCtl(t Fataler, fss ...zx.Tree) {
	if len(fss) == 0 {
		t.Fatalf("no fs given")
	}
	fs := fss[0].(zx.RWTree)
	vals := []bool{false, true}
	outs := []string{"debug off", "debug on"}
	for i, v := range vals {
		d := fs.(zx.Debugger).Debug()
		*d = v
		printf("get ctl: (debug %v)\n", v)
		dat, err := zx.GetAll(fs, "/Ctl")
		if err != nil {
			t.Fatalf("get /ctl: %s", err)
		}
		ctls := string(dat)
		printf("<%s>\n\n", ctls)
		if !strings.Contains(ctls, outs[i]) {
			t.Fatalf("wrong ctl output")
		}
	}
}

func PutCtl(t Fataler, fss ...zx.Tree) {
	if len(fss) == 0 {
		t.Fatalf("no fs given")
	}
	fs := fss[0].(zx.RWTree)
	vals := []bool{false, true, false, true}
	ins := []string{"nodebug", "debug", "debug off", "debug on"}
	outs := []string{"debug off", "debug on", "debug off", "debug on"}
	for i, v := range vals {
		printf("put ctl: (debug %v)\n", v)
		err := zx.PutAll(fs, "/Ctl", nil, []byte(ins[i]))
		if err != nil {
			t.Fatalf("put /ctl: %s", err)
		}
		printf("get ctl: (debug %v)\n", v)
		dat, err := zx.GetAll(fs, "/Ctl")
		if err != nil {
			t.Fatalf("get /ctl: %s", err)
		}
		ctls := string(dat)
		printf("<%s>\n\n", ctls)
		if !strings.Contains(ctls, outs[i]) {
			t.Fatalf("wrong ctl output")
		}
	}
	err := zx.PutAll(fs, "/Ctl", nil, []byte("bad ctl request"))
	if err == nil {
		t.Fatalf("bad put did not fail")
	}
	printf("put sts %s\n", err)
}


func PutsBench(b *testing.B, xfs zx.Tree) {
	fs := xfs.(zx.RWTree)
	b.StopTimer()
	var buf [1024]byte
	copy(buf[0:], "hola")
	<-fs.Remove("/nfb")
	b.StartTimer()
	for bi := 0; bi < b.N; bi++ {
		dc := make(chan []byte)
		xc := fs.Put("/nfb", zx.Dir{"mode": "0644"}, 0, dc, "")
		for i := 0; i < 128; i++ {
			if ok := dc <- buf[:]; !ok {
				b.Fatalf("put failed")
			}
		}
		close(dc)
		if len(<-xc) == 0 {
			b.Fatalf("put failed")
		}
	}
}

var (
	MkdirPaths    = []string{"/nd", "/nd/nd2", "/nd/nd22", "/nd/nd23", "/nd3"}
	BadMkdirPaths = []string{"/", "/nd", "/a"}
)

func Mkdirs(t Fataler, fss ...zx.Tree) {
	if len(fss) == 0 {
		t.Fatalf("no fs given")
	}
	fs := fss[0].(zx.RWTree)
	for i := 0; i < Repeats; i++ {
		for _, p := range MkdirPaths {
			printf("mkdir %s\n", p)
			ec := fs.Mkdir(p, zx.Dir{"mode": "0750"})
			err := <-ec
			if i>0 && err==nil {
				t.Fatalf("could re-mkdir %s", p)
			}
			if i==0 && err!=nil {
				t.Fatalf("%s: %s", p, err)
			}
			for _, fs := range fss {
				d, err := zx.Stat(fs, p)
				if err!=nil || d["type"]!="d" || d["mode"]!="0750" {
					t.Fatalf("mkdir not there %v %v", err, d)
				}
			}
		}
		for _, p := range BadMkdirPaths {
			printf("mkdir %s\n", p)
			ec := fs.Mkdir(p, zx.Dir{"mode": "0750"})
			err := <-ec
			if err == nil {
				t.Fatalf("mkdir %s worked", p)
			}
		}
	}
}

var (
	RemovePaths    = []string{"/d", "/e/f", "/e", "/a/a2"}
	BadRemovePaths = []string{"/", "/xxx", "/a"}
)

func Removes(t Fataler, fss ...zx.Tree) {
	if len(fss) == 0 {
		t.Fatalf("no fs given")
	}
	fs := fss[0].(zx.RWTree)
	for i := 0; i < Repeats; i++ {
		for _, p := range RemovePaths {
			printf("remove %s\n", p)
			ec := fs.Remove(p)
			err := <-ec
			if i>0 && err==nil {
				t.Fatalf("could re-remove %s", p)
			}
			if i==0 && err!=nil {
				t.Fatalf("%s: %s", p, err)
			}
			for _, fs := range fss {
				d, err := zx.Stat(fs, p)
				if err==nil || d!=nil {
					t.Fatalf("%s still there", p)
				}
			}
		}
		for _, p := range BadRemovePaths {
			ec := fs.Remove(p)
			err := <-ec
			if err == nil {
				t.Fatalf("remove %s worked", p)
			}
		}
	}
}

func MkdirRemoveBench(b *testing.B, xfs zx.Tree) {
	fs := xfs.(zx.RWTree)
	b.StopTimer()
	<-fs.Remove("/mrb")
	b.StartTimer()
	for bi := 0; bi < b.N; bi++ {
		xc := fs.Mkdir("/mrb", zx.Dir{"mode": "0755"})
		if <-xc != nil {
			b.Fatalf("mkdir failed")
		}
		xc = fs.Remove("/mrb")
		if <-xc != nil {
			b.Fatalf("remove failed")
		}
	}
}

type WstatTest  {
	Path  string
	Dir   zx.Dir
	AppDir bool
	Res   string
	Fails bool
}

var WstatTests = []WstatTest{
	{
		Path: "/d",
		Dir:  zx.Dir{"mode": "0704", "foo": "bar"},
		Res:  `path /d name d type d mode 0704 size 0`,
	},
	{
		Path: "/e/f",
		Dir:  zx.Dir{"mode": "0704", "foo": "bar"},
		Res:  `path /e/f name f type d mode 0704 size 0`,
	},
	{
		Path: "/e",
		Dir:  zx.Dir{"mode": "0704", "foo": "bar"},
		Res:  `path /e name e type d mode 0704 size 1`,
	},
	{
		Path: "/a/a2",
		Dir:  zx.Dir{"mode": "0704", "foo": "bar"},
		Res:  `path /a/a2 name a2 type - mode 0704 size 21418`,
	},
	{
		Path: "/",
		Dir:  zx.Dir{"mode": "0704", "foo": "bar"},
		Res:  `path / name / type d mode 0704 size 0`,
	},
	{
		Path:  "/xxx",
		Dir:   zx.Dir{"mode": "0704", "foo": "bar"},
		Fails: true,
	},
	{
		Path:  "/a/xxx",
		Dir:   zx.Dir{"mode": "0704", "foo": "bar"},
		Fails: true,
	},
	{
		Path:  "/dx",
		Dir:   zx.Dir{"mode": "0704", "foo": "bar"},
		Fails: true,
	},
}

func Wstats(t Fataler, fss ...zx.Tree) {
	if len(fss) == 0 {
		t.Fatalf("no fs given")
	}
	fs := fss[0].(zx.RWTree)
	for i := 0; i < Repeats; i++ {
		for _, f := range WstatTests {
			printf("wstat %s %v\n", f.Path, f.Dir)
			ec := fs.Wstat(f.Path, f.Dir)
			err := <-ec
			if f.Fails {
				if err == nil {
					t.Fatalf("%s didn't fail", f.Path)
				}
				continue
			}
			if !f.Fails && err!=nil {
				t.Fatalf("%s: %s", f.Path, err)
			}
			for _, fs := range fss {
				d, err := zx.Stat(fs, f.Path)
				if err != nil {
					t.Fatalf("stat %s: %s", f.Path, err)
				}
				if d["path"] == "/" {
					d["size"] = "0" // ctl, chg
				}
				if d.TestFmt() != f.Res {
					t.Logf("for %s\n", fs.Name())
					t.Logf("expected %s\n", f.Res)
					t.Logf("got %s\n", d.TestFmt())
					t.Fatalf("stat %s: didn't wstat it", f.Path)
				}
			}
		}
	}
}

var UsrWstatTests = []WstatTest{
	// extra bits in mode
	{
		Path: "/a",
		Dir:  zx.Dir{"mode": "07755"},
		Res: `path /a name a type d mode 0755 size 3 Gid nemo Uid nemo Wuid nemo`,
	},
	// changing size in a dir is ignored if writing existing attributes.
	{
		Path: "/a",
		Dir:  zx.Dir{"size": "5"},
		AppDir: true,
		Res: `path /a name a type d mode 0755 size 3 Gid nemo Uid nemo Wuid nemo`,
	},
	// writing a non  user attribute
	{
		Path: "/a",
		Dir:  zx.Dir{"foo": "bar"},
		Fails: true,
	},
	// writing a ignored non  user attribute
	{
		Path: "/a",
		Dir:  zx.Dir{"mtime": "0", "foo": "bar"},
		Res: `path /a name a type d mode 0755 size 3 Gid nemo Uid nemo Wuid nemo`,
	},
	// Adding a user attribute
	{
		Path: "/a",
		Dir:  zx.Dir{"Dir": "X"},
		Res: `path /a name a type d mode 0755 size 3 Dir X Gid nemo Uid nemo Wuid nemo`,
	},
	// Same, using the previous dir
	{
		Path: "/a",
		Dir:  zx.Dir{"Dir": "X"},
		AppDir: true,
		Res: `path /a name a type d mode 0755 size 3 Dir X Gid nemo Uid nemo Wuid nemo`,
	},
	// Adding a two user attributes
	{
		Path: "/a",
		Dir:  zx.Dir{"Dir": "X", "Abc": "A"},
		Res: `path /a name a type d mode 0755 size 3 Abc A Dir X Gid nemo Uid nemo Wuid nemo`,
	},
	// Removing a non existing user attribute
	{
		Path: "/a",
		Dir:  zx.Dir{"Non": ""},
		Res: `path /a name a type d mode 0755 size 3 Abc A Dir X Gid nemo Uid nemo Wuid nemo`,
	},
	// Rewriting a user attribute
	{
		Path: "/a",
		Dir:  zx.Dir{"Abc": "B"},
		Res: `path /a name a type d mode 0755 size 3 Abc B Dir X Gid nemo Uid nemo Wuid nemo`,
	},
	// Removing a user attribute
	{
		Path: "/a",
		Dir:  zx.Dir{"Abc": ""},
		Res: `path /a name a type d mode 0755 size 3 Dir X Gid nemo Uid nemo Wuid nemo`,
	},
	// Type change
	{
		Path: "/a",
		Dir:  zx.Dir{"type": "x"},
		Fails: true,
	},
	// Removing a sys attribute
	{
		Path: "/a",
		Dir:  zx.Dir{"type": "", "Dir": "X"},
		Fails: true,
	},
	// Trying to change size
	{
		Path: "/a",
		Dir:  zx.Dir{"size": "55"},
		Fails: true,
	},
	// Bad path
	{
		Path: "2",
		Dir:  zx.Dir{"size": "55"},
		Fails: true,
	},
	// Truncating a file
	{
		Path: "/2",
		Dir:  zx.Dir{"size": "55"},
		Res: `path /2 name 2 type - mode 0644 size 55 Gid nemo Uid nemo Wuid nemo`,
	},
}

func UsrWstats(t Fataler, fss ...zx.Tree) {
	if len(fss) == 0 {
		t.Fatalf("no fs given")
	}
	fs := fss[0].(zx.RWTree)
	for i := 0; i < 1; i++ {
		for _, f := range UsrWstatTests {
			d := f.Dir.Dup()
			if f.AppDir {
				od, err := zx.Stat(fs, f.Path)
				if err != nil {
					t.Fatalf("stat %s: %s", f.Path, err)
				}
				for k, v := range d {
					od[k] = v
				}
				d = od
			}
			printf("wstat %s %s\n", f.Path, d.LongTestFmt())
			ec := fs.Wstat(f.Path, d)
			err := <-ec
			if f.Fails {
				if err == nil {
					t.Fatalf("%s didn't fail", f.Path)
				}
				continue
			}
			if !f.Fails && err!=nil {
				t.Fatalf("%s: %s", f.Path, err)
			}
			for _, fs := range fss {
				d, err := zx.Stat(fs, f.Path)
				if err != nil {
					t.Fatalf("stat %s: %s", f.Path, err)
				}
				printf("result %s %s\n", f.Path, d.LongTestFmt())
				if d["foo"] != "" {
					t.Fatalf("could write foo")
				}
				if f.Res == "" {
					continue
				}
				if d["path"] == "/" {
					d["size"] = "0" // ctl, chg
				}
				delete(d, "Sum")
				ds := strings.Replace(d.LongTestFmt(), "nemo", "none", -1)
				ds2 := strings.Replace(f.Res, "nemo", "none", -1)
				if ds != ds2 {
					t.Logf("for fs %s\n", fs.Name())
					t.Logf("expected %s\n", f.Res)
					t.Logf("got %s\n", d.LongTestFmt())
					t.Fatalf("stat %s: didn't wstat it", f.Path)
				}
			}
		}
	}
}

func WstatBench(b *testing.B, xfs zx.Tree) {
	fs := xfs.(zx.RWTree)
	for bi := 0; bi < b.N; bi++ {
		xc := <-fs.Wstat("/e", zx.Dir{"mode": "0755"})
		if xc != nil {
			b.Fatalf("wstat failed")
		}
	}
}

var SendOuts = []string{
	`/`,
	`path /1 name 1 type - mode 0644 size 0`,
	`path /2 name 2 type - mode 0644 size 31658`,
	`path /a name a type d mode 0755 size 3`,
	`path /a/a1 name a1 type - mode 0644 size 10154`,
	`path /a/a2 name a2 type - mode 0644 size 21418`,
	`path /a/b name b type d mode 0755 size 1`,
	`path /a/b/c name c type d mode 0755 size 1`,
	`path /a/b/c/c3 name c3 type - mode 0644 size 44970`,
	`path /d name d type d mode 0755 size 0`,
	`path /e name e type d mode 0755 size 1`,
	`path /e/f name f type d mode 0755 size 0`,
}

func SendRecv(t Fataler, sfs, rfs zx.RWTree) {
	dc := make(chan []byte)
	rf, err := zx.Stat(sfs, "/")
	if err!=nil || rf==nil {
		t.Fatalf("stat: %s", err)
	}
	zx.DebugSend = testing.Verbose()
	go func() {
		err := zx.Send(sfs, rf, dc)
		close(dc, err)
	}()
	err = zx.Recv(rfs, dc)
	if cerror(dc) != nil {
		t.Logf("send err %s", cerror(dc))
	}
	if err != nil {
		t.Fatalf("recv: %s", err)
	}
	err = cerror(dc)
	if err != nil {
		t.Fatalf("send: %s", err)
	}
	fc := rfs.Find("/", "", "/", "/", 0)
	tot := 0
	outs := []string{}
	for d := range fc {
		printf("\t`%s`,\n", d.LongTestFmt())
		if d["path"] == "/" {
			outs = append(outs, "/")
			tot++
			continue
		}
		if d["path"] == "/" {
			d["size"] = "0" // get rid of ctl, chg
		}
		if d["path"]=="/Ctl" || d["path"]=="/Chg" {
			continue
		}
		tot++
		outs = append(outs, d.TestFmt())
	}
	if tot != 12 {
		t.Fatalf("bad find tot: got %d", tot)
	}
	if strings.Join(outs, "\n") != strings.Join(SendOuts, "\n") {
		t.Fatalf("bad received tree")
	}
}

// Check out if fs.Dump() is the same for all trees
func SameDump(t Fataler, fss ...zx.Tree) {
	old := ""
	oname := ""
	nname := ""
	for _, tfs := range fss {
		var buf bytes.Buffer
		fs, ok := tfs.(zx.Dumper)
		if !ok {
			continue
		}
		fs.Dump(&buf)
		ns := buf.String()
		toks := strings.SplitN(ns, "\n", 2)
		if len(toks) > 1 {
			ns = toks[1]
			nname = toks[0]
		}
		if old == "" {
			old = ns
			oname = nname
		} else if old != ns {
			t.Logf("%s\n<%s>\n", oname, old)
			t.Logf("%s\n<%s>\n", nname, ns)
			i := 0
			for i < len(old) && i < len(ns) {
				if old[i] != ns[i] {
					break
				}
				i++
			}
			t.Logf("suffix1 <%s>\n", old[i:])
			t.Logf("suffix2 <%s>\n", ns[i:])
			t.Fatalf("trees do not match")
		}
	}
}
コード例 #24
0
ファイル: races.go プロジェクト: Christopheraburns/clive
func rstat(t Fataler, fs zx.RWTree, fname string) {
	zx.Stat(fs, fname)
}
コード例 #25
0
ファイル: arch.go プロジェクト: Christopheraburns/clive
func dump(dir string, t zx.Tree, ec chan bool) {
	defer func() {
		ec <- true
	}()
	name := t.Name()
	data := zx.Path(dir, "data")
	doskip := Skip
	for {
		if doskip {
			waitDumpTime(name)
			doskip = false
			continue
		}
		dbg.Warn("snap %s...", name)
		if err := os.MkdirAll(data, 0750); err != nil {
			dbg.Warn("%s: %s", data, err)
			return
		}
		rd, err := zx.Stat(t, "/")
		if err != nil {
			dbg.Warn("%s: %s", name, err)
			continue
		}
		// make sure it's not empty
		ds, err := zx.GetDir(t, "/")
		if err != nil {
			dbg.Warn("%s: %s", name, err)
			continue
		}
		if len(ds) == 0 {
			dbg.Warn("%s: file system is empty. ignored.", name)
			continue
		}
		s, err := dumpDir(data, name, zx.File{t, rd})
		if err != nil {
			dbg.Warn("%s: %s", name, err)
		}
		ts := time.Now().Format("2006/0102")
		tree := strings.Replace(name, "/", ".", -1)
		tspath0 := zx.Path(dir, tree, ts)
		os.MkdirAll(path.Dir(tspath0), 0755)
		spath := zx.Path(data, s)
		tspath := tspath0
		for i := 1; ; i++ {
			fi, _ := os.Stat(tspath)
			if fi == nil {
				break
			}
			tspath = fmt.Sprintf("%s.%d", tspath0, i)
		}
		os.MkdirAll(path.Dir(tspath), 0755)
		if err := os.Symlink(spath, tspath); err != nil {
			dbg.Warn("%s: %s", name, err)
		}
		dbg.Warn("snap %s %s", tspath, s)
		if Once {
			break
		}
		waitDumpTime(name)
	}
}