blob: dcf4cc5dba5026fd6965a95ad9b1e60b9b529cb9 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// A test for the PerSyncgroup table in blobmap.
package blobmap_test
import "io/ioutil"
import "os"
import "testing"
import "v.io/v23/verror"
import "v.io/x/ref/services/syncbase/localblobstore"
import "v.io/x/ref/services/syncbase/localblobstore/blobmap"
import "v.io/x/ref/services/syncbase/server/interfaces"
import "v.io/x/ref/services/syncbase/store"
import "v.io/x/ref/test"
import _ "v.io/x/ref/runtime/factories/generic"
// perSyncgroupEqual() returns whether *a and *b are equal.
// We do not use reflect.DeepEqual(), because PerSyncgroup contains time.Time values,
// whose useless Location field is often different, even though the time is the same.
// Currently, it checks only the Priority.Distance field.
func perSyncgroupEqual(a *localblobstore.PerSyncgroup, b *localblobstore.PerSyncgroup) bool {
return a.Priority.Distance == b.Priority.Distance
}
// TestAddRetrieveAndDeletePerSyncgroup() tests insertion, retrieval, and deletion
// of PerSyncgroup entries from a BlobMap. It's all done in one test case, because
// one cannot retrieve or delete PerSyncgroup entries that have not been inserted.
func TestAddRetrieveAndDeletePerSyncgroup(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
// Make a temporary directory.
var err error
var testDirName string
testDirName, err = ioutil.TempDir("", "blobmap_test")
if err != nil {
t.Fatalf("blobmap_test: can't make tmp directory: %v", err)
}
defer os.RemoveAll(testDirName)
// Create a blobmap.
var bm *blobmap.BlobMap
bm, err = blobmap.New(ctx, store.EngineForTest, testDirName)
if err != nil {
t.Fatalf("blobmap_test: blobmap.New failed: %v", err)
}
// Two syncgroup IDs: sgs[0] and sgs[1].
// Mimic actual syncgroup IDs: 43-byte strings.
sgs := []interfaces.GroupId{"foofoofoofoofoofoofoofoofoofoofoofoofoofoo0", "barbarbarbarbarbarbarbarbarbarbarbarbarbar1"}
var psg localblobstore.PerSyncgroup
var psgList []localblobstore.PerSyncgroup
for i := range sgs {
err = bm.GetPerSyncgroup(ctx, sgs[i], &psg)
if err == nil {
t.Errorf("blobmap_test: blob: %v already has a PerSyncgroup", sgs[i])
}
}
for i := range sgs {
psg.Priority.Distance = 17
psgList = append(psgList, psg)
err = bm.SetPerSyncgroup(ctx, sgs[i], &psg)
if err != nil {
t.Errorf("blobmap_test: SetPerSyncgroup(%v, %v) got error: %v", sgs[i], psg, err)
}
}
for i := range sgs {
err = bm.GetPerSyncgroup(ctx, sgs[i], &psg)
if err != nil {
t.Errorf("blobmap_test: GetPerSyncgroup(%v) got error: %v", sgs[i], err)
} else if !perSyncgroupEqual(&psg, &psgList[i]) {
t.Errorf("blobmap_test: GetPerSyncgroup(%v) got wrong content: %v, want %v", sgs[i], psg, psgList[i])
}
}
// Test iteration through the PerSyncgroup entries.
count := 0
psgs := bm.NewPerSyncgroupStream(ctx)
for psgs.Advance() {
sg := psgs.SyncgroupId()
psg = psgs.PerSyncgroup()
// Find the syncgroup in the list.
var i int
for i = 0; i != len(sgs) && sg != sgs[i]; i++ {
}
if i == len(sgs) {
t.Errorf("blobmap_test: PerSyncgroupStream iteration %d, got syncgropup name %v, which is not in %v", count, sg, sgs)
} else if !perSyncgroupEqual(&psg, &psgList[i]) {
t.Errorf("blobmap_test: PerSyncgroupStream iteration %d, sgs[%d]=%v, got PerSyncgroup %v, want %v", count, i, sg, psg, psgList[i])
}
count++
}
if count != len(sgs) {
t.Errorf("blobmap_test: PerSyncgroupStream got %d elements, wanted %d", count, len(sgs))
}
if err = psgs.Err(); err != nil {
t.Errorf("blobmap_test: PerSyncgroupStream unexpectedly gave error: %v", err)
}
// Test cancellation after first element retrieved.
count = 0
psgs = bm.NewPerSyncgroupStream(ctx)
for psgs.Advance() {
psgs.Cancel()
count++
}
if count != 1 {
t.Errorf("blobmap_test: PerSyncgroupStream unexpectedly didn't give one element; got %d", count)
}
if err = psgs.Err(); verror.ErrorID(err) != verror.ErrCanceled.ID {
t.Errorf("blobmap_test: PerSyncgroupStream unexpectedly wasn't cancelled: err is %v", err)
}
// Delete the first PerSyncgroup.
if err = bm.DeletePerSyncgroup(ctx, sgs[0]); err != nil {
t.Errorf("blobmap_test: DeletePerSyncgroup(%v) got error: %v", sgs[0], err)
}
// Check that we can no longer get the first element, and we can get the others.
for i := range sgs {
err = bm.GetPerSyncgroup(ctx, sgs[i], &psg)
if i == 0 {
if err == nil {
t.Errorf("blobmap_test: GetPerSyncgroup(%v) unexpectedly failed to get error on deleted blob, returned %v", sgs[i], psg)
}
} else if err != nil {
t.Errorf("blobmap_test: GetPerSyncgroup(%v) got error: %v", sgs[i], err)
} else if !perSyncgroupEqual(&psg, &psgList[i]) {
t.Errorf("blobmap_test: GetPerSyncgroup(%v) got wrong content: %v, want %v", sgs[i], psg, psgList[i])
}
}
// Test iteration with first PerSyncgroup deleted.
count = 0
psgs = bm.NewPerSyncgroupStream(ctx)
for psgs.Advance() {
sg := psgs.SyncgroupId()
psg = psgs.PerSyncgroup()
// Find the blob in the list, ignoring the first.
var i int
for i = 1; i != len(sgs) && sg != sgs[i]; i++ {
}
if i == len(sgs) {
t.Errorf("blobmap_test: PerSyncgroupStream iteration %d, got syncgroup name %v, which is not in %v", count, sg, sgs[1:])
} else if !perSyncgroupEqual(&psg, &psgList[i]) {
t.Errorf("blobmap_test: PerSyncgroupStream iteration %d, sgs[%d]=%v, got PerSyncgroup %v, want %v", count, i, sg, psg, psgList[i])
}
count++
}
if count != len(sgs)-1 {
t.Errorf("blobmap_test: PerSyncgroupStream got %d elements, wanted %d", count, len(sgs)-1)
}
if err = psgs.Err(); err != nil {
t.Errorf("blobmap_test: PerSyncgroupStream unexpectedly gave error: %v", err)
}
// Delete remaining PerSyncgroup entries.
for i := 1; i != len(sgs); i++ {
if err = bm.DeletePerSyncgroup(ctx, sgs[i]); err != nil {
t.Errorf("blobmap_test: DeletePerSyncgroup(%v) got error: %v", sgs[i], err)
}
}
// Check that all the elements are no longer there.
for i := range sgs {
err = bm.GetPerSyncgroup(ctx, sgs[i], &psg)
if err == nil {
t.Errorf("blobmap_test: GetPerSyncgroup(%v) unexpectedly failed to get error on deleted blob, returned %v", sgs[i], psg)
}
}
// Check that iteration finds nothing.
count = 0
psgs = bm.NewPerSyncgroupStream(ctx)
for psgs.Advance() {
count++
}
if count != 0 {
t.Errorf("blobmap_test: PerSyncgroupStream unexpectedly didn't give zero elements; got %d", count)
}
if err = psgs.Err(); err != nil {
t.Errorf("blobmap_test: PerSyncgroupStream unexpectedly got error: %v", err)
}
err = bm.Close()
if err != nil {
t.Errorf("blobmap_test: unexpected error closing BlobMap: %v", err)
}
}