Example #1
0
func TestPing(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()

	var wg sync.WaitGroup
	defer wg.Wait()
	web1 := httptest.ServeHTTP(t, &wg, app1)
	defer web1.Close()

	pub1 := (*peer.PublicKey)(app1.Keys.Sign.Pub)
	pub2 := (*peer.PublicKey)(app2.Keys.Sign.Pub)

	setup1 := func(tx *db.Tx) error {
		if _, err := tx.Peers().Make(pub2); err != nil {
			return err
		}
		return nil
	}
	if err := app1.DB.Update(setup1); err != nil {
		t.Fatalf("app1 setup: %v", err)
	}

	setup2 := func(tx *db.Tx) error {
		p, err := tx.Peers().Make(pub1)
		if err != nil {
			return err
		}
		if err := p.Locations().Set(web1.Addr().String()); err != nil {
			return err
		}
		return nil
	}
	if err := app2.DB.Update(setup2); err != nil {
		t.Fatalf("app2 setup location: %v", err)
	}

	client, err := app2.DialPeer(pub1)
	if err != nil {
		t.Fatalf("dial: %v", err)
	}
	defer client.Close()

	ctx := context.Background()
	if _, err := client.Ping(ctx, &wire.PingRequest{}); err != nil {
		t.Errorf("ping failed: %v", err)
	}
}
Example #2
0
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)
	}
}
Example #3
0
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")
	}
}
Example #4
0
func TestSyncPull(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()

	var wg sync.WaitGroup
	defer wg.Wait()
	web1 := httptest.ServeHTTP(t, &wg, app1)
	defer web1.Close()

	pub1 := (*peer.PublicKey)(app1.Keys.Sign.Pub)
	pub2 := (*peer.PublicKey)(app2.Keys.Sign.Pub)

	var volID db.VolumeID
	sharingKey := [32]byte{42, 42, 42, 13}
	const volumeName = "foo"

	setup1 := func(tx *db.Tx) error {
		sharingKey, err := tx.SharingKeys().Add("testkey", &sharingKey)
		if err != nil {
			return err
		}
		v, err := tx.Volumes().Create(volumeName, "local", sharingKey)
		if err != nil {
			return err
		}
		v.VolumeID(&volID)
		p, err := tx.Peers().Make(pub2)
		if err != nil {
			return err
		}
		if err := p.Volumes().Allow(v); err != nil {
			return err
		}
		if err := p.Storage().Allow("local"); err != nil {
			return err
		}
		return nil
	}
	if err := app1.DB.Update(setup1); err != nil {
		t.Fatalf("app1 setup: %v", err)
	}

	setup2 := func(tx *db.Tx) error {
		sharingKey, err := tx.SharingKeys().Add("testkey", &sharingKey)
		if err != nil {
			return err
		}
		v, err := tx.Volumes().Add(volumeName, &volID, "local", sharingKey)
		if err != nil {
			return err
		}
		v.VolumeID(&volID)
		p, err := tx.Peers().Make(pub1)
		if err != nil {
			return err
		}
		if err := v.Storage().Add("jdoe", "peerkey:"+pub1.String(), sharingKey); err != nil {
			return err
		}
		if err := p.Locations().Set(web1.Addr().String()); err != nil {
			return err
		}
		return nil
	}
	if err := app2.DB.Update(setup2); err != nil {
		t.Fatalf("app2 setup location: %v", err)
	}

	var chunkStore2 chunks.Store
	openKV := func(tx *db.Tx) error {
		// This cannot be combined into setup2 because OpenKV/DialPeer
		// starts its own transaction, and wouldn't see the
		// uncommitted peer.
		v, err := tx.Volumes().GetByVolumeID(&volID)
		if err != nil {
			return err
		}
		kvstore, err := app2.OpenKV(tx, v.Storage())
		if err != nil {
			return err
		}
		chunkStore2 = kvchunks.New(kvstore)
		return nil
	}
	if err := app2.DB.View(openKV); err != nil {
		t.Fatalf("cannot open storage for app2: %v", err)
	}

	const testFileName = "greeting"
	const testFileContent = "hello, world"
	func() {
		mnt := bazfstestutil.Mounted(t, app1, volumeName)
		defer mnt.Close()
		if err := ioutil.WriteFile(path.Join(mnt.Dir, testFileName), []byte(testFileContent), 0644); err != nil {
			t.Fatalf("cannot create file: %v", err)
		}
	}()

	client, err := app2.DialPeer(pub1)
	if err != nil {
		t.Fatalf("dial: %v", err)
	}
	defer client.Close()

	volIDBuf, err := volID.MarshalBinary()
	if err != nil {
		t.Fatalf("marshal volume id: %v", err)
	}
	ctx := context.Background()
	stream, err := client.VolumeSyncPull(ctx, &wire.VolumeSyncPullRequest{
		VolumeID: volIDBuf,
	})
	if err != nil {
		t.Fatalf("sync failed: %v", err)
	}

	item, err := stream.Recv()
	if err != nil {
		t.Fatalf("sync stream failed: %v", err)
	}
	if g, e := item.Error, wire.VolumeSyncPullItem_SUCCESS; g != e {
		t.Errorf("unexpected error: %v != %v", g, e)
	}
	if g, e := item.Peers, map[uint32][]byte{
		0: pub1[:],
		1: pub2[:],
	}; !reflect.DeepEqual(g, e) {
		t.Errorf("bad peers: %v != %v", g, e)
	}

	wantFiles := map[string]func(*wire.Dirent){
		testFileName: func(de *wire.Dirent) {
			if de.File == nil {
				t.Errorf("wrong type for %q, not a file: %v", de.Name, de)
				return
			}

			var c clock.Clock
			if err := c.UnmarshalBinary(de.Clock); err != nil {
				t.Errorf("invalid clock for %q: %v", de.Name, err)
				return
			}
			if g, e := c.String(), `{sync{0:1} mod{0:1} create{0:1}}`; g != e {
				t.Errorf("wrong clock for %q: %v != %v", de.Name, g, e)
				return
			}

			// verify file contents
			manifest, err := de.File.Manifest.ToBlob("file")
			if err != nil {
				t.Errorf("cannot open manifest for %q: %v", de.Name, err)
				return
			}
			blob, err := blobs.Open(chunkStore2, manifest)
			if err != nil {
				t.Errorf("cannot open blob for %q: %v", de.Name, err)
				return
			}
			r := io.NewSectionReader(blob, 0, int64(blob.Size()))
			buf, err := ioutil.ReadAll(r)
			if err != nil {
				t.Errorf("cannot read blob for %q: %v", de.Name, err)
				return
			}
			if g, e := string(buf), testFileContent; g != e {
				t.Errorf("wrong content for %q: %q != %q", de.Name, g, e)
			}
		},
	}
	for _, de := range item.Children {
		fn, ok := wantFiles[de.Name]
		if !ok {
			t.Errorf("unexpected direntry: %q", de.Name)
			continue
		}
		fn(de)
		delete(wantFiles, de.Name)
	}
	for name, _ := range wantFiles {
		t.Errorf("missing direntry: %q", name)
	}

	item, err = stream.Recv()
	if err != io.EOF {
		t.Errorf("expected eof, got error %v, item=%v", err, item)
	}
}
Example #5
0
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)
	}

}