func TestSharingAdd(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app, err := server.New(tmp.Path) if err != nil { t.Fatal(err) } var wg sync.WaitGroup defer wg.Wait() ctrl := controltest.ListenAndServe(t, &wg, app) defer ctrl.Close() secret := [32]byte{1, 2, 3, 4, 5} addReq := &wire.SharingKeyAddRequest{ Name: "foo", Secret: secret[:], } rpcConn, err := grpcunix.Dial(filepath.Join(app.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() if _, err := rpcClient.SharingKeyAdd(ctx, addReq); err != nil { t.Fatalf("adding sharing key failed: %v", err) } check := func(tx *db.Tx) error { sharingKey, err := tx.SharingKeys().Get("foo") if err != nil { t.Fatalf("error checking sharing key: %v", err) } var key [32]byte sharingKey.Secret(&key) if g, e := key, secret; g != e { t.Errorf("wrong secret stored: %x != %x", g, e) } return nil } if err := app.DB.View(check); err != nil { t.Error(err) } }
func TestPeerAdd(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app, err := server.New(tmp.Path) if err != nil { t.Fatal(err) } var wg sync.WaitGroup defer wg.Wait() ctrl := controltest.ListenAndServe(t, &wg, app) defer ctrl.Close() pub := peer.PublicKey{1, 2, 3, 4, 5} addReq := &wire.PeerAddRequest{ Pub: pub[:], } rpcConn, err := grpcunix.Dial(filepath.Join(app.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() if _, err := rpcClient.PeerAdd(ctx, addReq); err != nil { t.Fatalf("adding peer failed: %v", err) } getPeer := func(tx *db.Tx) error { p, err := tx.Peers().Get(&pub) if err != nil { t.Fatalf("checking stored peer: %v", err) } if g, e := *p.Pub(), pub; g != e { t.Errorf("wrong public key stored: %x != %x", g, e) } return nil } if err := app.DB.View(getPeer); err != nil { t.Fatal(err) } }
func TestSharingAddBadNameEmpty(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app, err := server.New(tmp.Path) if err != nil { t.Fatal(err) } var wg sync.WaitGroup defer wg.Wait() ctrl := controltest.ListenAndServe(t, &wg, app) defer ctrl.Close() secret := [32]byte{1, 2, 3, 4, 5} addReq := &wire.SharingKeyAddRequest{ Name: "", Secret: secret[:], } rpcConn, err := grpcunix.Dial(filepath.Join(app.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() _, err = rpcClient.SharingKeyAdd(ctx, addReq) if err == nil { t.Fatalf("expected error from SharingKeyAdd with empty name") } if err := checkRPCError(err, codes.InvalidArgument, "invalid sharing key name"); err != nil { t.Error(err) } if err := app.DB.View(checkNoSharingKey("foo")); err != nil { t.Error(err) } }
func TestSharingAddBadSecretShort(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app, err := server.New(tmp.Path) if err != nil { t.Fatal(err) } var wg sync.WaitGroup defer wg.Wait() ctrl := controltest.ListenAndServe(t, &wg, app) defer ctrl.Close() tooShort := make([]byte, 33) addReq := &wire.SharingKeyAddRequest{ Name: "foo", Secret: tooShort, } rpcConn, err := grpcunix.Dial(filepath.Join(app.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() _, err = rpcClient.SharingKeyAdd(ctx, addReq) if err == nil { t.Fatalf("expected error from SharingKeyAdd with too short secret") } if err := checkRPCError(err, codes.InvalidArgument, "sharing key must be exactly 32 bytes"); err != nil { t.Error(err) } if err := app.DB.View(checkNoSharingKey("foo")); err != nil { t.Error(err) } }
func TestPeerAddBadPubLong(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app, err := server.New(tmp.Path) if err != nil { t.Fatal(err) } var wg sync.WaitGroup defer wg.Wait() ctrl := controltest.ListenAndServe(t, &wg, app) defer ctrl.Close() tooLong := make([]byte, 33) addReq := &wire.PeerAddRequest{ Pub: tooLong, } rpcConn, err := grpcunix.Dial(filepath.Join(app.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() _, err = rpcClient.PeerAdd(ctx, addReq) if err == nil { t.Fatalf("expected error from PeerAdd with too long public key") } if err := checkRPCError(err, codes.InvalidArgument, "bad peer public key: peer public key must be exactly 32 bytes"); err != nil { t.Error(err) } if err := checkHasNoPeers(app); err != nil { t.Error(err) } }
func TestPeerAddBadPubSelf(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app, err := server.New(tmp.Path) if err != nil { t.Fatal(err) } var wg sync.WaitGroup defer wg.Wait() ctrl := controltest.ListenAndServe(t, &wg, app) defer ctrl.Close() addReq := &wire.PeerAddRequest{ Pub: app.Keys.Sign.Pub[:], } rpcConn, err := grpcunix.Dial(filepath.Join(app.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() _, err = rpcClient.PeerAdd(ctx, addReq) if err == nil { t.Fatalf("expected error from PeerAdd with its own public key") } if err := checkRPCError(err, codes.InvalidArgument, "cannot add self as peer"); err != nil { t.Error(err) } if err := checkHasNoPeers(app); err != nil { t.Error(err) } }
func TestSyncSimple(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app1 := bazfstestutil.NewApp(t, tmp.Subdir("app1")) defer app1.Close() app2 := bazfstestutil.NewApp(t, tmp.Subdir("app2")) defer app2.Close() pub1 := (*peer.PublicKey)(app1.Keys.Sign.Pub) const ( volumeName1 = "testvol1" volumeName2 = "testvol2" ) connectVolume(t, app1, volumeName1, app2, volumeName2) var wg sync.WaitGroup defer wg.Wait() web1 := httptest.ServeHTTP(t, &wg, app1) defer web1.Close() setLocation(t, app2, app1.Keys.Sign.Pub, web1.Addr()) const ( filename = "greeting" input = "hello, world" ) func() { mnt := bazfstestutil.Mounted(t, app1, volumeName1) defer mnt.Close() if err := ioutil.WriteFile(path.Join(mnt.Dir, filename), []byte(input), 0644); err != nil { t.Fatalf("cannot create file: %v", err) } }() // trigger sync ctrl := controltest.ListenAndServe(t, &wg, app2) defer ctrl.Close() rpcConn, err := grpcunix.Dial(filepath.Join(app2.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() req := &wire.VolumeSyncRequest{ VolumeName: volumeName2, Pub: pub1[:], } if _, err := rpcClient.VolumeSync(ctx, req); err != nil { t.Fatalf("error while syncing: %v", err) } mnt := bazfstestutil.Mounted(t, app2, volumeName2) defer mnt.Close() buf, err := ioutil.ReadFile(path.Join(mnt.Dir, filename)) if err != nil { t.Fatalf("cannot read file: %v", err) } if g, e := string(buf), input; g != e { t.Fatalf("wrong content: %q != %q", g, e) } }
func TestSyncDeleteActive(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app1 := bazfstestutil.NewApp(t, tmp.Subdir("app1")) defer app1.Close() app2 := bazfstestutil.NewApp(t, tmp.Subdir("app2")) defer app2.Close() pub1 := (*peer.PublicKey)(app1.Keys.Sign.Pub) const ( volumeName1 = "testvol1" volumeName2 = "testvol2" ) connectVolume(t, app1, volumeName1, app2, volumeName2) var wg sync.WaitGroup defer wg.Wait() web1 := httptest.ServeHTTP(t, &wg, app1) defer web1.Close() setLocation(t, app2, app1.Keys.Sign.Pub, web1.Addr()) const ( filename = "greeting" input = "hello, world" ) mnt1 := bazfstestutil.Mounted(t, app1, volumeName1) defer mnt1.Close() if err := ioutil.WriteFile(path.Join(mnt1.Dir, filename), []byte(input), 0644); err != nil { t.Fatalf("cannot create file: %v", err) } mnt2 := bazfstestutil.Mounted(t, app2, volumeName2) defer mnt2.Close() { proto, err := mnt2.Protocol() if err != nil { t.Errorf("error getting FUSE protocol version: %v", err) } if !proto.HasInvalidate() { t.Skip("Old FUSE protocol") } } // trigger sync ctrl := controltest.ListenAndServe(t, &wg, app2) defer ctrl.Close() rpcConn, err := grpcunix.Dial(filepath.Join(app2.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() req := &wire.VolumeSyncRequest{ VolumeName: volumeName2, Pub: pub1[:], } if _, err := rpcClient.VolumeSync(ctx, req); err != nil { t.Fatalf("error while syncing: %v", err) } buf, err := ioutil.ReadFile(path.Join(mnt2.Dir, filename)) if err != nil { t.Fatalf("cannot read file: %v", err) } if g, e := string(buf), input; g != e { t.Fatalf("wrong content: %q != %q", g, e) } if err := os.Remove(path.Join(mnt1.Dir, filename)); err != nil { t.Fatalf("cannot create file: %v", err) } // sync again if _, err := rpcClient.VolumeSync(ctx, req); err != nil { t.Fatalf("error while syncing: %v", err) } if _, err := os.Stat(path.Join(mnt2.Dir, filename)); !os.IsNotExist(err) { t.Fatalf("file should have been removed") } }
func TestSyncOpen(t *testing.T) { tmp := tempdir.New(t) defer tmp.Cleanup() app1 := bazfstestutil.NewApp(t, tmp.Subdir("app1")) defer app1.Close() app2 := bazfstestutil.NewApp(t, tmp.Subdir("app2")) defer app2.Close() pub1 := (*peer.PublicKey)(app1.Keys.Sign.Pub) const ( volumeName1 = "testvol1" volumeName2 = "testvol2" ) connectVolume(t, app1, volumeName1, app2, volumeName2) var wg sync.WaitGroup defer wg.Wait() web1 := httptest.ServeHTTP(t, &wg, app1) defer web1.Close() setLocation(t, app2, app1.Keys.Sign.Pub, web1.Addr()) mnt1 := bazfstestutil.Mounted(t, app1, volumeName1) defer mnt1.Close() mnt2 := bazfstestutil.Mounted(t, app2, volumeName2) defer mnt2.Close() const ( filename = "greeting" input = "hello, world" ) if err := ioutil.WriteFile(path.Join(mnt1.Dir, filename), []byte(input), 0644); err != nil { t.Fatalf("cannot create file: %v", err) } // trigger sync ctrl := controltest.ListenAndServe(t, &wg, app2) defer ctrl.Close() rpcConn, err := grpcunix.Dial(filepath.Join(app2.DataDir, "control")) if err != nil { t.Fatal(err) } defer rpcConn.Close() rpcClient := wire.NewControlClient(rpcConn) ctx := context.Background() req := &wire.VolumeSyncRequest{ VolumeName: volumeName2, Pub: pub1[:], } if _, err := rpcClient.VolumeSync(ctx, req); err != nil { t.Fatalf("error while syncing: %v", err) } f, err := os.Open(path.Join(mnt2.Dir, filename)) if err != nil { t.Fatalf("cannot open file: %v", err) } defer f.Close() { var buf [1000]byte n, err := f.ReadAt(buf[:], 0) if err != nil && err != io.EOF { t.Fatalf("cannot read file: %v", err) } if g, e := string(buf[:n]), input; g != e { t.Fatalf("wrong content: %q != %q", g, e) } } const input2 = "goodbye, world" if err := ioutil.WriteFile(path.Join(mnt1.Dir, filename), []byte(input2), 0644); err != nil { t.Fatalf("cannot update file: %v", err) } // sync again if _, err := rpcClient.VolumeSync(ctx, req); err != nil { t.Fatalf("error while syncing: %v", err) } { // still the original content var buf [1000]byte n, err := f.ReadAt(buf[:], 0) if err != nil && err != io.EOF { t.Fatalf("cannot read file: %v", err) } if g, e := string(buf[:n]), input; g != e { t.Fatalf("wrong content: %q != %q", g, e) } } f.Close() // after the close, new content should be merged in // // TODO observing the results is racy :( time.Sleep(500 * time.Millisecond) buf, err := ioutil.ReadFile(path.Join(mnt2.Dir, filename)) if err != nil { t.Fatalf("cannot read file: %v", err) } if g, e := string(buf), input2; g != e { t.Fatalf("wrong content: %q != %q", g, e) } }