Exemple #1
0
func TestTreeSync(t *testing.T) {
	db, fn := mkrtest(t, rtdir)
	defer fn()
	db.Close()
	db, fn2 := mktest(t, tdir)
	defer fn2()
	db.Close()

	tr, err := New("adb", tdir, "unix!local!9988!/p")
	if err != nil {
		t.Fatalf("tree %s", err)
	}
	tr.Debug = testing.Verbose()
	tr.Rdb.Debug = testing.Verbose()
	defer tr.Close()
	fstest.MkChgs(t, tdir)
	fstest.MkChgs2(t, rtdir+"/p")
	dprintf("\nsync\n")
	cc, dc := getChgs()
	err = tr.Sync(cc)
	if err != nil {
		t.Fatalf("sync %s", err)
	}
	cs := <-dc
	logChgs(cs)
	chkFiles(t, tr.Ldb, nil, "")
	chkFiles(t, tr.Rdb, nil, "")
	os.RemoveAll(tdir + ".pull")
	os.Rename(tdir, tdir+".pull")
	os.RemoveAll(rtdir + ".push")
	os.Rename(rtdir+"/p", rtdir+".push")
}
Exemple #2
0
func TestTreePush(t *testing.T) {
	db, fn := mkrtest(t, rtdir)
	defer fn()
	db.Close()
	db, fn2 := mktest(t, tdir)
	defer fn2()
	db.Close()

	tr, err := New("adb", tdir, "unix!local!9988!/p")
	if err != nil {
		t.Fatalf("tree %s", err)
	}
	tr.Debug = testing.Verbose()
	tr.Rdb.Debug = testing.Verbose()
	defer tr.Close()
	fstest.MkChgs(t, tdir)
	fstest.MkChgs2(t, rtdir+"/p")
	chkFiles(t, tr.Ldb, fstest.AllFiles, fstest.AllFilesList)
	chkFiles(t, tr.Rdb, fstest.AllFiles, fstest.AllFilesList)
	dprintf("\npush\n")
	cc, dc := getChgs()
	err = tr.BlindPush(cc)
	if err != nil {
		t.Fatalf("push %s", err)
	}
	cs := <-dc
	logChgs(cs)
	cmpChgs(t, pushcs, cs)
	chkFiles(t, tr.Ldb, nil, pushldb)
	chkFiles(t, tr.Rdb, nil, pushrdb)
	os.RemoveAll(rtdir + ".push")
	os.Rename(rtdir+"/p", rtdir+".push")
}
Exemple #3
0
func TestSync0Chgs(t *testing.T) {
	fstest.ResetTime()
	fstest.MkTree(t, tdir)
	defer fstest.RmTree(t, tdir)
	fstest.ResetTime()
	fstest.MkTree(t, tdir2)
	defer fstest.RmTree(t, tdir2)
	fstest.MkChgs(t, tdir2)
	fs, err := lfs.New(tdir, tdir, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	fs2, err := lfs.New(tdir2, tdir2, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	Debug = moreverb
	fs.Dbg = moreverb
	fs2.Dbg = moreverb
	fs.SaveAttrs(true)
	fs2.SaveAttrs(true)

	db, err := NewDB("tdb", "", fs)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
	}
	db2, err := NewDB("tdb2", "", fs2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	if testing.Verbose() {
		db2.DumpTo(os.Stdout)
	}
	pulls := []chg{
		chg{Type: Data, Path: "/a/a1"},
		chg{Type: Meta, Path: "/a/a2"},
		chg{Type: Add, Path: "/a/n"},
	}
	pushes := []chg{
		chg{Type: Add, Path: "/a/b/c"},
	}
	pullc, pushc := Changes(db, db2)
	ec := make(chan error, 2)
	go chkcc("pull", pullc, pulls, ec)
	go chkcc("push", pushc, pushes, ec)
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
		db2.DumpTo(os.Stdout)
	}
}
Exemple #4
0
func TestTreeSaveLoad(t *testing.T) {

	db, fn := mkrtest(t, rtdir)
	defer fn()
	db.Close()
	db, fn2 := mktest(t, tdir)
	defer fn2()
	db.Close()
	fstest.MkChgs(t, tdir)
	fstest.MkChgs2(t, rtdir+"/p")
	os.Remove(tdir + "repl.ldb")
	os.Remove(tdir + "repl.rdb")
	defer os.Remove(tdir + "repl.ldb")
	defer os.Remove(tdir + "repl.rdb")
	tr, err := New("adb", tdir, "unix!local!9988!/p")
	if err != nil {
		t.Fatalf("tree %s", err)
	}
	tr.Debug = testing.Verbose()
	tr.Rdb.Debug = testing.Verbose()
	defer tr.Close()
	dprintf("\ninitial:\n")
	chkFiles(t, tr.Ldb, nil, "")
	chkFiles(t, tr.Rdb, nil, "")

	dprintf("\nsave & load:\n")
	if err := tr.Save(tdir + "repl"); err != nil {
		t.Fatalf("save %s", err)
	}
	if tr, err = Load(tdir + "repl"); err != nil {
		t.Fatalf("load %s", err)
	}
	chkFiles(t, tr.Ldb, nil, "")
	chkFiles(t, tr.Rdb, nil, "")

	// now continue as in the previous test, to check
	// it all is ok.
	dprintf("\npullall\n")
	cc, dc := getChgs()
	err = tr.PullAll(cc)
	if err != nil {
		t.Fatalf("pullall %s", err)
	}
	dprintf("\npullall done\n")
	cs := <-dc
	logChgs(cs)
	chkFiles(t, tr.Ldb, nil, pullrdb)
	chkFiles(t, tr.Rdb, nil, pullrdb)
	os.RemoveAll(tdir + ".pull")
	os.Rename(tdir, tdir+".pull")
	os.RemoveAll(rtdir + ".push")
	os.Rename(rtdir+"/p", rtdir+".push")

}
Exemple #5
0
func TestTreeAllPushChanges(t *testing.T) {
	db, fn := mkrtest(t, rtdir)
	defer fn()
	db.Close()
	db, fn2 := mktest(t, tdir)
	defer fn2()
	db.Close()

	tr, err := New("adb", tdir, "unix!local!9988!/p")
	if err != nil {
		t.Fatalf("tree %s", err)
	}
	tr.Debug = testing.Verbose()
	tr.Rdb.Debug = testing.Verbose()
	defer tr.Close()
	dprintf("\ndiffs before making changes\n")
	cc, err := tr.AllPushChanges()
	if err != nil {
		t.Fatalf("sync %s", err)
	}
	chgs := []Chg{}
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s\n", c)
	}
	cmpChgs(t, pushdchgs, chgs)

	dprintf("\ndiffs after making changes\n")
	fstest.MkChgs(t, tdir)
	fstest.MkChgs2(t, rtdir+"/p")
	cc, err = tr.AllPushChanges()
	if err != nil {
		t.Fatalf("sync %s", err)
	}
	chgs = []Chg{}
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg2 %s\n", c)
	}
	cmpChgs(t, pushdchgs2, chgs)

	os.RemoveAll(tdir + ".pull")
	os.Rename(tdir, tdir+".pull")
	os.RemoveAll(rtdir + ".push")
	os.Rename(rtdir+"/p", rtdir+".push")
}
Exemple #6
0
func TestTreeChanges(t *testing.T) {
	db, fn := mkrtest(t, rtdir)
	defer fn()
	db.Close()
	db, fn2 := mktest(t, tdir)
	defer fn2()
	db.Close()

	tr, err := New("adb", tdir, "unix!local!9988!/p")
	if err != nil {
		t.Fatalf("tree %s", err)
	}
	tr.Debug = testing.Verbose()
	defer tr.Close()
	fstest.MkChgs(t, tdir)
	fstest.MkChgs2(t, rtdir+"/p")
	dprintf("pull\n")
	cc, err := tr.PullChanges()
	if err != nil {
		t.Fatalf("pull %s", err)
	}
	for c := range cc {
		dprintf("chg %s %s\n", c.At, c)
	}
	dprintf("push\n")
	cc, err = tr.PushChanges()
	if err != nil {
		t.Fatalf("push %s", err)
	}
	for c := range cc {
		dprintf("chg %s %s\n", c.At, c)
	}
	dprintf("sync\n")
	cc, err = tr.Changes()
	if err != nil {
		t.Fatalf("sync %s", err)
	}
	chgs := []Chg{}
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s %s\n", c.At, c)
	}
	cmpChgs(t, schg, chgs)
}
Exemple #7
0
func TestDiffs(t *testing.T) {
	os.Args[0] = "fscmp.test"
	fstest.Verb = testing.Verbose()
	fstest.MkTree(t, tdir)
	fstest.MkChgs(t, tdir)
	defer os.RemoveAll(tdir)
	fstest.ResetTime()
	fstest.MkTree(t, tdir2)
	fstest.MkChgs2(t, tdir2)
	defer os.RemoveAll(tdir2)

	Printf("changes...\n")
	fs, err := zux.NewZX(tdir)
	if err != nil {
		t.Fatal(err)
	}
	fs2, err := zux.NewZX(tdir2)
	if err != nil {
		t.Fatal(err)
	}
	rc := Diff(fs, fs2)
	out := ""
	for c := range rc {
		s := fmt.Sprintf("chg %s %s\n", c.Type, c.D.Fmt())
		Printf("%s", s)
		out += s
	}
	xout := `chg data - rw-r--r--     50 /1
chg dirfile d rwxr-x---      0 /2
chg data - rw-r--r--   9.9k /a/a1
chg meta - rw-r--r--  20.9k /a/a2
chg add d rwxr-xr-x      0 /a/b/c
chg add - rw-r--r--  43.9k /a/b/c/c3
chg del d rwxr-x---      0 /a/n
chg del d rwxr-x---      0 /a/n/m
chg del - rw-r-----     11 /a/n/m/m1
`
	if out != xout {
		t.Fatalf("bad set of changes")
	}
}
Exemple #8
0
func TestCmp(t *testing.T) {
	db, fn := mktest(t, tdir)
	defer fn()
	fstest.MkChgs(t, tdir)
	dprintf("db after changes\n")
	ndb := mkdb(t, tdir)
	chkFiles(t, ndb, fstest.AllChgFiles, fstest.AllChgFilesList)

	cc := ndb.ChangesFrom(db)
	chgs := []Chg{}
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s\n", c)
	}
	cmpChgs(t, chg1, chgs)
	fstest.MkChgs2(t, tdir)
	dprintf("\ndb after changes2\n")
	ndb2 := mkdb(t, tdir)
	chkFiles(t, ndb2, fstest.AllChg2Files, fstest.AllChg2FilesList)

	dprintf("\nchanges...\n")
	chgs = []Chg{}
	cc = ndb2.ChangesFrom(ndb)
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s\n", c)
	}
	cmpChgs(t, chg2, chgs)
	dprintf("all chgs\n")
	chgs = []Chg{}
	cc = ndb2.ChangesFrom(db)
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s\n", c)
	}
	cmpChgs(t, chg3, chgs)
}
Exemple #9
0
func TestRzxCmp(t *testing.T) {
	db, fn := mkrtest(t, rtdir)
	defer fn()
	fstest.MkChgs(t, rtdir+"/p")
	dprintf("db after changes\n")
	ndb := mkdb(t, "unix!local!9988!/p")
	chkFiles(t, ndb, fstest.AllChgFiles, fstest.AllChgFilesList)
	defer ndb.Close()
	cc := ndb.ChangesFrom(db)
	chgs := []Chg{}
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s\n", c)
	}
	cmpChgs(t, chg1, chgs)
	fstest.MkChgs2(t, rtdir+"/p")
	dprintf("\ndb after changes2\n")
	ndb2 := mkdb(t, "unix!local!9988!/p")
	chkFiles(t, ndb2, fstest.AllChg2Files, fstest.AllChg2FilesList)
	defer ndb2.Close()
	chgs = []Chg{}
	cc = ndb2.ChangesFrom(ndb)
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s\n", c)
	}
	cmpChgs(t, chg2, chgs)
	dprintf("all chgs\n")
	chgs = []Chg{}
	cc = ndb2.ChangesFrom(db)
	for c := range cc {
		chgs = append(chgs, c)
		dprintf("chg %s\n", c)
	}
	cmpChgs(t, chg3, chgs)
}
Exemple #10
0
func TestApplyChgs(t *testing.T) {
	fstest.ResetTime()
	fstest.MkTree(t, tdir)
	defer fstest.RmTree(t, tdir)
	fstest.ResetTime()
	fstest.MkTree(t, tdir2)
	defer fstest.RmTree(t, tdir2)
	fs, err := lfs.New(tdir, tdir, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	fs2, err := lfs.New(tdir2, tdir2, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	Debug = moreverb
	fs.Dbg = moreverb
	fs2.Dbg = moreverb
	fs.SaveAttrs(true)
	fs2.SaveAttrs(true)

	// Initial dbs
	db, err := NewDB("tdb", "", fs)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	db2, err := NewDB("tdb2", "", fs2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}

	// Make changes to db and update its db
	fstest.MkChgs2(t, tdir)
	ndb, err := NewDB("tndb", "", fs)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	cc := db.ChangesTo(ndb)
	ec := make(chan error, 1)
	go chkcc("upd", cc, nil, ec)
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	db = ndb
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
	}

	// Make changes to db2 and update its db
	fstest.MkChgs(t, tdir2)
	ndb2, err := NewDB("tndb2", "", fs2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	cc = db2.ChangesTo(ndb2)
	ec = make(chan error, 1)
	go chkcc("upd2", cc, nil, ec)
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	db2 = ndb2
	if testing.Verbose() {
		db2.DumpTo(os.Stdout)
	}

	// Now apply changes
	pullc, pushc := Changes(db, db2)
	ec = make(chan error, 2)
	errsc := make(chan error)
	go func() {
		for e := range errsc {
			printf("err %s\n", e)
		}
	}()
	go func() {
		for c := range pullc {
			printf("pull %s\n", c)
			if err := c.Apply(fs, fs2, "", errsc); err != nil {
				close(pullc, err)
				ec <- err
				return
			}
		}
		ec <- nil
	}()
	go func() {
		for c := range pushc {
			printf("push %s\n", c)
			if err := c.Apply(fs2, fs, "", errsc); err != nil {
				close(pushc, err)
				ec <- err
				return
			}
		}
		ec <- nil
	}()
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	close(errsc)
	db.Update(fs)
	db2.Update(fs2)
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
		db2.DumpTo(os.Stdout)
	}
	var b, b2 bytes.Buffer
	db2.Name = db.Name
	db.DumpTo(&b)
	db2.DumpTo(&b2)
	if strings.Replace(b.String(), dbg.Usr, "none", -1) !=
		strings.Replace(b2.String(), dbg.Usr, "none", -1) {
		t.Fatal("dbs do not match")
	}
}
Exemple #11
0
func TestSyncChgs(t *testing.T) {
	fstest.ResetTime()
	fstest.MkTree(t, tdir)
	defer fstest.RmTree(t, tdir)
	fstest.ResetTime()
	fstest.MkTree(t, tdir2)
	defer fstest.RmTree(t, tdir2)
	fs, err := lfs.New(tdir, tdir, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	fs2, err := lfs.New(tdir2, tdir2, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	Debug = moreverb
	fs.Dbg = moreverb
	fs2.Dbg = moreverb
	fs.SaveAttrs(true)
	fs2.SaveAttrs(true)

	// Initial dbs
	db, err := NewDB("tdb", "", fs)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
	}
	db2, err := NewDB("tdb2", "", fs2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	if testing.Verbose() {
		db2.DumpTo(os.Stdout)
	}

	// Make changes to db and update its db
	fstest.MkChgs2(t, tdir)
	ndb, err := NewDB("tndb", "", fs)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	cc := db.ChangesTo(ndb)
	ec := make(chan error, 1)
	go chkcc("upd", cc, nil, ec)
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	db = ndb
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
	}

	// Make changes to db2 and update its db
	fstest.MkChgs(t, tdir2)
	ndb2, err := NewDB("tndb2", "", fs2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	cc = db2.ChangesTo(ndb2)
	ec = make(chan error, 1)
	go chkcc("upd2", cc, nil, ec)
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	db2 = ndb2
	if testing.Verbose() {
		db2.DumpTo(os.Stdout)
	}

	// Now sync
	pulls := []chg{
		chg{Type: Data, Path: "/a/a1"},
		chg{Type: Meta, Path: "/a/a2"},
		chg{Type: Del, Path: "/a/b/c"},
		chg{Type: Add, Path: "/a/n"},
	}
	pushes := []chg{
		chg{Type: Data, Path: "/1"},
		chg{Type: DirFile, Path: "/2"},
	}

	pullc, pushc := Changes(db, db2)
	ec = make(chan error, 2)
	go chkcc("pull", pullc, pulls, ec)
	go chkcc("push", pushc, pushes, ec)
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
		db2.DumpTo(os.Stdout)
	}

}
Exemple #12
0
func TestUpdate(t *testing.T) {
	fstest.ResetTime()
	fstest.MkTree(t, tdir)
	defer fstest.RmTree(t, tdir)
	fstest.ResetTime()
	fstest.MkTree(t, tdir2)
	defer fstest.RmTree(t, tdir2)
	fs, err := lfs.New(tdir, tdir, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	fs2, err := lfs.New(tdir2, tdir2, lfs.RW)
	if err != nil {
		t.Fatalf("new lfs: %s", err)
	}
	Debug = moreverb
	fs.Dbg = moreverb
	fs2.Dbg = moreverb
	fs.SaveAttrs(true)
	fs2.SaveAttrs(true)

	// Initial dbs
	db, err := NewDB("tdb", "", fs)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	if testing.Verbose() {
		db.DumpTo(os.Stdout)
	}
	db2, err := NewDB("tdb2", "", fs2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	if testing.Verbose() {
		db2.DumpTo(os.Stdout)
	}

	// Make changes to db2 and update its db
	fstest.MkChgs(t, tdir2)
	ndb2, err := NewDB("tndb2", "", fs2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	cc := db2.ChangesTo(ndb2)
	ec := make(chan error, 1)
	go chkcc("upd2", cc, nil, ec)
	if e := <-ec; e != nil {
		t.Fatal(e)
	}
	if testing.Verbose() {
		ndb2.DumpTo(os.Stdout)
	}

	if err := db2.Update(fs2); err != nil {
		t.Fatalf("update: %s", err)
	}
	var b1, b2 bytes.Buffer
	ndb2.Name = db2.Name
	ndb2.DumpTo(&b1)
	db2.DumpTo(&b2)
	if b1.String() != b2.String() {
		t.Fatalf("dbs do not match")
	}
}
Exemple #13
0
func TestSyncChgs(t *testing.T) {
	fstest.ResetTime()
	fstest.RmTree(t, rdir)
	fstest.RmTree(t, tdir)
	fstest.RmTree(t, tdir2)
	defer fstest.RmTree(t, tdir2)
	defer fstest.RmTree(t, rdir)
	defer fstest.RmTree(t, tdir)
	if err := os.Mkdir(rdir, 0755); err != nil && !dbg.IsExists(err) {
		t.Fatalf("%s: %s", tdir2, err)
	}
	fstest.MkTree(t, tdir)
	if err := os.Mkdir(tdir2, 0755); err != nil {
		t.Fatalf("%s: %s", tdir2, err)
	}

	r, err := New("testrepl", "", tdir, tdir2)
	if err != nil {
		t.Fatalf("new: %s", err)
	}
	if err := r.Sync(); err != nil {
		t.Fatalf("sync: %s", err)
	}
	if err := r.Save(rcfg); err != nil {
		t.Fatalf("save: %s", err)
	}

	r, err = Load(rcfg)
	if err != nil {
		t.Fatalf("load: %s", err)
	}
	if testing.Verbose() {
		r.DumpTo(os.Stdout)
	}

	fstest.MkChgs2(t, tdir)
	fstest.MkChgs(t, tdir2)

	if err := r.Sync(); err != nil {
		t.Fatalf("sync: %s", err)
	}
	if testing.Verbose() {
		r.DumpTo(os.Stdout)
	}

	if err := r.Sync(); err != nil {
		t.Fatalf("sync: %s", err)
	}
	if err := r.Save(rcfg); err != nil {
		t.Fatalf("save: %s", err)
	}
	if err := r.Sync(); err != nil {
		t.Fatalf("sync: %s", err)
	}
	var b bytes.Buffer
	r.DumpTo(&b)
	out := `testrepl '' /tmp/db_test /tmp/db_test2
testrepl[/tmp/db_test]
/              d 0755 none     none     none            6
/1             - 0644 none     none     none           50 13000000000
/2             d 0750 none     none     none            1
/2/n2          d 0750 none     none     none            0
/a             d 0755 none     none     none            4
/a/a1          - 0644 none     none     none        10154 14000000000
/a/a2          - 0750 none     none     none        21418 2000000000
/a/b           d 0755 none     none     none            0
/a/b/c         d GONE none     none     none            1
/a/n           d 0750 none     none     none            1
/a/n/m         d 0750 none     none     none            1
/a/n/m/m1      - 0640 none     none     none           11 15000000000
/d             d 0755 none     none     none            0
/e             d 0755 none     none     none            1
/e/f           d 0755 none     none     none            0
testrepl[/tmp/db_test2]
/              d 0755 none     none     none            6
/1             - 0644 none     none     none           50 13000000000
/2             d 0750 none     none     none            1
/2/n2          d 0750 none     none     none            0
/a             d 0755 none     none     none            4
/a/a1          - 0644 none     none     none        10154 14000000000
/a/a2          - 0750 none     none     none        21418 2000000000
/a/b           d 0755 none     none     none            0
/a/b/c         d GONE none     none     none            1
/a/n           d 0750 none     none     none            1
/a/n/m         d 0750 none     none     none            1
/a/n/m/m1      - 0640 none     none     none           11 15000000000
/d             d 0755 none     none     none            0
/e             d 0755 none     none     none            1
/e/f           d 0755 none     none     none            0
`
	if strings.Replace(b.String(), dbg.Usr, "none", -1) != out {
		t.Fatal("bad repl")
	}
}