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) } }
func mklfstrees(t *testing.T) (zx.RWTree, zx.RWTree) { fstest.MkTree(t, tdir) lfs1, err := lfs.New(tdir, tdir, lfs.RW) if err != nil { t.Fatalf("lfs: %s", err) } lfs2, err := lfs.New(tdir, tdir, lfs.RW) if err != nil { t.Fatalf("lfs: %s", err) } return lfs1, lfs2 }
func TestInitDirs(t *testing.T) { os.Args[0] = "mdfs_test" os.RemoveAll(tlfsdir) defer os.RemoveAll(tlfsdir) if err := os.Mkdir(tlfsdir, 0755); err != nil { t.Fatalf("lfs: %s", err) } dfs, err := lfs.New(" cache", tlfsdir, lfs.RW) if err != nil { t.Fatalf("lfs: %s", err) } dfs.SaveAttrs(true) dfs.Dbg = moreverb && testing.Verbose() fs, err := New("example mdfs", dfs) if err != nil { t.Fatalf("mdfs: %s", err) } fs.Dbg = testing.Verbose() if fs.Dbg { defer func() { fs.Dbg = false dfs.Dbg = false fs.Dump(os.Stdout) dfs.Dump(os.Stdout) }() } for _, dn := range fstest.Dirs { if err := zx.MkdirAll(fs, dn, zx.Dir{"mode": "0755"}); err != nil { t.Fatalf("mkdir: %s", err) } } }
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) }
func lfscache(t zx.Tree, fn func()) (zx.Tree, func(), error) { m, err := lfs.New("clfs", lfsdir, lfs.RW) if err != nil { return nil, nil, fmt.Errorf("lfs", err) } m.SaveAttrs(true) m.IOstats = &zx.IOstats{} m.Dbg = zdebug ncfs.Debug = zdebug xfs, err := ncfs.New("cfs", m, t, rflag) if err != nil { return nil, nil, fmt.Errorf("cfs: %s", err) } st := &zx.IOstats{} xfs.IOstats = st if xaddr != "" { serve(xfs, xaddr) } if sflag { xfn := func() { st.Averages() dbg.Warn("%s iostats:\n%s\n", xfs.Name(), st) if fn != nil { fn() } } return xfs, xfn, nil } return xfs, fn, nil }
/* Import the remote ZX server at the given address. This performs authentication if auth.Enabled and honors TLS configuration. Addresses of the form "*!*!lfs!tree!/a/b" are understood as a request to build a local fs at the given path. An address referring to a existing dir path is also used to build a local fs. */ func Import(addr string) (zx.RWTree, error) { if fi, err := os.Stat(addr); err == nil && fi.IsDir(){ dir, err := filepath.Abs(addr) if err != nil { return nil, err } fs, err := lfs.New(addr, dir, lfs.RW) if err == nil { fs.SaveAttrs(true) } return fs, err } toks := strings.Split(addr, "!") if len(toks) < 2 { return nil, errors.New("bad address") } if len(toks) < 3 { toks = append(toks, "zx") addr = strings.Join(toks, "!") } if toks[2] == "lfs" { p := "/" if len(toks) >= 5 { p = toks[4] } fs, err := lfs.New(addr, p, lfs.RW) if err == nil { fs.SaveAttrs(true) } return fs, err } tree := "main" if len(toks) >= 4 { tree = toks[3] } c, err := ds.Dial(addr) if err != nil { return nil, err } if _, err := auth.AtClient(c, "", "zx"); err!=nil && err!=auth.ErrDisabled { err = fmt.Errorf("auth: %s", err) close(c.In, err) close(c.Out, err) return nil, err } return New(nchan.NewMux(c, true), tree) }
func TestSendRecv(t *testing.T) { t.Skip("TODO: this does not work but we are no longer sending trees") os.RemoveAll(tlfsdir + "2") os.RemoveAll(tlfsdir) if err := os.Mkdir(tlfsdir, 0755); err != nil { t.Fatalf("lfs: %s", err) } if err := os.Mkdir(tlfsdir+"2", 0755); err != nil { t.Fatalf("lfs: %s", err) } defer os.RemoveAll(tlfsdir + "2") defer os.RemoveAll(tlfsdir) os.Args[0] = "mdfs_test" dfs1, err := lfs.New(" cache1", tlfsdir, lfs.RW) if err != nil { t.Fatalf("lfs: %s", err) } dfs1.SaveAttrs(true) fs1, err := New("example mfs1", dfs1) if err != nil { t.Fatalf("mdfs: %s", err) } fs1.Dbg = testing.Verbose() fstest.MkZXTree(t, fs1) dfs2, err := lfs.New(" cache2", tlfsdir+"2", lfs.RW) if err != nil { t.Fatalf("lfs: %s", err) } dfs2.SaveAttrs(true) fs2, err := New("example mfs2", dfs2) if err != nil { t.Fatalf("mdfs: %s", err) } if fs1.Dbg { defer fs2.Dump(os.Stdout) defer fs1.Dump(os.Stdout) } fstest.SendRecv(t, fs1, fs2) }
func TestCmpNoChg(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) 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) } cc := db.ChangesTo(db2) ec := make(chan error, 1) chkcc("chgs", cc, []chg{}, ec) if e := <-ec; e != nil { t.Fatal(e) } }
func main() { defer dbg.Exits("") os.Args[0] = "zxdump" dfltdump := zx.Path(dbg.Home, "dump") opts.NewFlag("s", "don't dump right now, wait until next at 5am", &Skip) opts.NewFlag("1", "dump once and exit", &Once) opts.NewFlag("v", "verbose", &Verbose) opts.NewFlag("D", "debug", &Debug) opts.NewFlag("x", "expr: files excluded (.*, tmp.* if none given); tmp always excluded.", &Xcludes) Dump = dfltdump opts.NewFlag("d", "dir: where to keep the dump, or empty if none", &Dump) args, err := opts.Parse(os.Args) if err != nil { dbg.Warn("%s", err) opts.Usage() dbg.Exits(err) } if len(Xcludes) == 0 { Xcludes = []string{".*", "tmp.*", "*.tmp"} } Xcludes = append(Xcludes, "tmp") if len(args) == 0 { dbg.Warn("arguments missing") opts.Usage() dbg.Exits("usage") } if Skip && Once { dbg.Fatal("can't skip the current dump and dump once now") } nt := 0 ec := make(chan bool) for i := 0; i < len(args); i++ { al := strings.SplitN(args[i], "!", 2) if len(al) == 1 { al = append(al, al[0]) al[0] = path.Base(al[0]) } t, err := lfs.New(al[0], al[1], lfs.RO) if err != nil { dbg.Warn("%s: %s", al[0], err) continue } t.ReadAttrs(true) nt++ go dump(Dump, t, ec) } if nt == 0 { dbg.Fatal("no trees to dump") } for nt > 0 { <-ec nt-- } }
// on-disk cache func dcache() (zx.RWTree, *zx.Flags, error) { m, err := lfs.New("clfs", lfscache, lfs.RW) if err != nil { return nil, nil, fmt.Errorf("lfs", err) } m.SaveAttrs(true) m.IOstats = &zx.IOstats{} m.Dbg = lfsdebug m.WstatAll = true // cfs must be able to write it all return m, m.Flags, nil }
func mklfs(path string) (zx.RWTree, *zx.Flags, *zx.IOstats, error) { ronly := rflag && nocache fs, err := lfs.New(path, path, ronly) if err != nil { return nil, nil, nil, fmt.Errorf("lfs: %s", err) } if sflag { fs.IOstats = &zx.IOstats{} } fs.Dbg = lfsdebug fs.SaveAttrs(true) return fs, fs.Flags, fs.IOstats, nil }
func ExampleNew() { // create a tree using the local directory /tmp/cache for the cache dfs, err := lfs.New("cache", "/tmp/cache", lfs.RW) if err != nil { dbg.Fatal("lfs: %s", err) } fs, err := New("example mdfs", dfs) if err != nil { dbg.Fatal("mfds: %s", err) } dbg.Warn("fs %s ready", fs) // Now use it... }
// on-memory medatadata, on-disk data cache func mdcache() (zx.RWTree, *zx.Flags, error) { d, err := lfs.New("mlfs", mlfscache, lfs.RW) if err != nil { return nil, nil, fmt.Errorf("lfs", err) } d.SaveAttrs(true) d.WstatAll = true // cfs must be able to write it all m, err := mdfs.New("mdfs", d) if err != nil { return nil, nil, fmt.Errorf("mdfs: %s", err) } m.IOstats = &zx.IOstats{} d.Dbg = lfsdebug && false m.Dbg = lfsdebug m.WstatAll = true // cfs must be able to write it all return m, m.Flags, nil }
func testfs(t fstest.Fataler) (*lfs.Lfs, *Rfs) { fs, err := lfs.New(tdir, tdir, lfs.RW) if err != nil { t.Fatalf("new: %s", err) } c1, c2 := nchan.NewConnPipe(0) srv := Serve("srv", c1, nil, RW, fs) srv.Debug = testing.Verbose() && moreverb rfs, err := New(nchan.NewMux(c2, true), "") if err != nil { t.Fatalf("%s", err) } rfs.Tag = "cli" rfs.Dbg = testing.Verbose() VerbDebug = moreverb return fs, rfs }
func TestNew(t *testing.T) { fstest.ResetTime() fstest.MkTree(t, tdir) defer fstest.RmTree(t, tdir) fs, err := lfs.New(tdir, tdir, lfs.RW) if err != nil { t.Fatalf("new lfs: %s", err) } fs.SaveAttrs(true) Debug = moreverb fs.Dbg = moreverb db, err := NewDB("tdb", "", fs) if err != nil { t.Fatalf("new: %s", err) } if testing.Verbose() { db.DumpTo(os.Stdout) } var b1 bytes.Buffer db.DumpTo(&b1) c := make(chan []byte, 1000) if err := db.SendTo(c); err != nil { t.Fatalf("recv: %s", err) } close(c) ndb, err := RecvDBFrom(c) if err != nil { t.Fatalf("recv: %s", err) } if testing.Verbose() { ndb.DumpTo(os.Stdout) } var b2 bytes.Buffer db.DumpTo(&b2) if b1.String() != b2.String() { t.Fatal("dbs do not match") } }
func TestFiles(t *testing.T) { fstest.ResetTime() fstest.MkTree(t, tdir) defer fstest.RmTree(t, tdir) fs, err := lfs.New(tdir, tdir, lfs.RW) if err != nil { t.Fatalf("new lfs: %s", err) } Debug = moreverb fs.Dbg = moreverb fs.SaveAttrs(true) db, err := NewDB("tdb", "", fs) if err != nil { t.Fatalf("new: %s", err) } n := 0 for f := range db.Files() { printf("%s\n", f) n++ } if n != 12 { t.Fatalf("got %d and not 12 entries", n) } }
func main() { defer dbg.Exits("") os.Args[0] = "zx" port = "8002" opts.NewFlag("p", "port: tcp server port (8002 by default)", &port) wport = "9002" opts.NewFlag("w", "port: wax http server port", &wport) svc = "zx" opts.NewFlag("s", "srv: service name (zx by default)", &svc) addr = "*!*!zx" opts.NewFlag("a", "addr: service address (*!*!zx by default)", &addr) opts.NewFlag("v", "report users logged in/out (verbose)", &Verbose) opts.NewFlag("D", "debug", &Debug) opts.NewFlag("Z", "verbose debug", &Zdebug) opts.NewFlag("M", "debug mutexes", &cfs.DebugLocks) nopings := false opts.NewFlag("k", "do not use zx keep alives", &nopings) args, err := opts.Parse(os.Args) if err != nil { usage(err) } if len(args) == 0 { usage(errors.New("missing arguments")) } Debug = Debug || Zdebug auth.Debug = Debug cfs.Debug = Debug rfs.Verb = Verbose var trs []zx.Tree var ros = map[bool]string{false: "rw", true: "ro"} for i := 0; i < len(args); i++ { al := strings.Split(args[i], "!") if len(al) == 1 { al = append(al, al[0]) al[0] = path.Base(al[0]) } ronly := false caching := true if len(al) == 3 && strings.Contains(al[2], "ro") { ronly = true } if len(al) == 3 && strings.Contains(al[2], "nc") { caching = false } t, err := lfs.New(al[0], al[1], ronly && !caching) if err != nil { dbg.Warn("%s: %s", al[0], err) continue } t.ReadAttrs(true) t.SaveAttrs(caching) t.IOstats = &zx.IOstats{} fp, _ := filepath.Abs(al[1]) if caching { dbg.Warn("%s mfs + lfs %s caching", al[0], ros[ronly]) cache, err := mfs.New("mfs:" + al[0]) if err != nil { dbg.Warn("%s: mfs: %s", al[0], err) continue } cache.IOstats = &zx.IOstats{} cache.Dbg = Zdebug cache.WstatAll = true // cfs must be able to write it all x, err := cfs.New(al[0], cache, t, ronly) if err != nil { dbg.Warn("%s: cfs: %s", al[0], err) continue } x.IOstats = &zx.IOstats{} zxw[al[0]] = fp trs = append(trs, x) } else { dbg.Warn("%s lfs %s uncached", al[0], ros[ronly]) zxw[al[0]] = fp t.Dbg = Debug trs = append(trs, t) } } if len(trs) == 0 { dbg.Fatal("no trees to serve") } ds.DefSvc(svc, port) Vprintf("%s: serve %s...\n", os.Args[0], addr) cc, _, err := ds.Serve(os.Args[0], addr) if err != nil { dbg.Fatal("%s: serve: %s", os.Args[0], err) } go zxwax() for c := range cc { go func(c nchan.Conn) { ai, err := auth.AtServer(c, "", "zx", "finder") if err != nil && err != auth.ErrDisabled { Vprintf("%s: auth %s: %s\n", os.Args[0], c.Tag, err) close(c.In, err) close(c.Out, err) return } srv := rfs.Serve("rfs:"+c.Tag, c, ai, rfs.RW, trs...) if false { srv.Debug = Debug } srv.Pings = !nopings }(*c) } if err := cerror(cc); err != nil { dbg.Fatal("%s: serve: %s", os.Args[0], err) } }
func main() { defer dbg.Exits("") os.Args[0] = "zx" port = "8002" opts.NewFlag("p", "port: tcp server port", &port) wport = "9002" opts.NewFlag("w", "port: wax http server port", &wport) svc = "zx" opts.NewFlag("s", "srv: service name", &svc) addr = "*!*!zx" opts.NewFlag("a", "addr: service address", &addr) opts.NewFlag("D", "debug", &Debug) opts.NewFlag("Z", "verbose debug", &Zdebug) opts.NewFlag("k", "make cfg entries persist in the ns", &Persist) opts.NewFlag("N", "use new cfs", &New) args, err := opts.Parse(os.Args) if err != nil { usage(err) } if len(args) == 0 { usage(nil) } Debug = Debug || Zdebug auth.Debug = Debug ncfs.Debug = Debug cfs.Debug = Debug cfs.Cdebug = Zdebug cfs.Zdebug = Zdebug rfs.Verb = Verbose var trs []zx.Tree var ros = map[bool]string{false: "rw", true: "ro"} for i := 0; i < len(args); i++ { al := strings.Split(args[i], "!") if len(al) == 1 { al = append(al, al[0]) al[0] = path.Base(al[0]) } ronly := false caching := true if len(al) == 3 && strings.Contains(al[2], "ro") { ronly = true } if len(al) == 3 && strings.Contains(al[2], "nc") { caching = false } t, err := lfs.New(al[0], al[1], ronly && !caching) if err != nil { dbg.Warn("%s: %s", al[0], err) continue } t.ReadAttrs(true) t.SaveAttrs(caching) t.IOstats = &zx.IOstats{} fp, _ := filepath.Abs(al[1]) if New && caching { dbg.Warn("%s mfs + lfs %s caching", al[0], ros[ronly]) cache, err := mfs.New("mfs:" + al[0]) if err != nil { dbg.Warn("%s: mfs: %s", al[0], err) continue } cache.IOstats = &zx.IOstats{} cache.Dbg = Zdebug x, err := ncfs.New("cfs", cache, t, ronly) if err != nil { dbg.Warn("%s: cfs: %s", al[0], err) continue } x.IOstats = &zx.IOstats{} zxw[al[0]] = fp trs = append(trs, x) } else if !New && caching { dbg.Warn("%s old cfs + lfs %s caching", al[0], ros[ronly]) x, err := cfs.New("", t, ronly) if err != nil { dbg.Warn("%s: cfs: %s", al[0], err) continue } x.IOstats = &zx.IOstats{} zxw[al[0]] = fp trs = append(trs, x) } else { dbg.Warn("%s lfs %s uncached", al[0], ros[ronly]) zxw[al[0]] = fp t.Dbg = Debug trs = append(trs, t) } } if len(trs) == 0 { dbg.Fatal("no trees to serve") } ds.DefSvc(svc, port) Vprintf("%s: serve %s...\n", os.Args[0], addr) cc, _, err := ds.Serve(os.Args[0], addr) if err != nil { dbg.Fatal("%s: serve: %s", os.Args[0], err) } go zxwax() for c := range cc { go func(c nchan.Conn) { ai, err := auth.AtServer(c, "", "zx", "finder") if err != nil && err != auth.ErrDisabled { Vprintf("%s: auth %s: %s\n", os.Args[0], c.Tag, err) close(c.In, err) close(c.Out, err) return } srv := rfs.Serve("rfs:"+c.Tag, c, ai, rfs.RW, trs...) if false { srv.Debug = Debug } }(*c) } if err := cerror(cc); err != nil { dbg.Fatal("%s: serve: %s", os.Args[0], err) } }
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") } }
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 }
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) } }
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") } }