replica: test minWritesForSuccess

Change-Id: I5c845e99b1c440c35bfb7a5a7865176fd72ae031
This commit is contained in:
Brad Fitzpatrick 2014-01-18 22:53:03 -08:00
parent cfeeda0fa9
commit e29c43bfde
3 changed files with 45 additions and 6 deletions

View File

@ -19,6 +19,7 @@ package replica
import (
"testing"
"camlistore.org/pkg/blob"
"camlistore.org/pkg/blobserver"
"camlistore.org/pkg/jsonconfig"
"camlistore.org/pkg/test"
@ -33,13 +34,9 @@ func newReplica(t *testing.T, config jsonconfig.Obj) *replicaStorage {
return sto.(*replicaStorage)
}
func TestReceive(t *testing.T) {
sto := newReplica(t, map[string]interface{}{
"backends": []interface{}{"/good-1/", "/good-2/"},
})
tb := &test.Blob{Contents: "stuff"}
func mustReceive(t *testing.T, dst blobserver.Storage, tb *test.Blob) blob.SizedRef {
tbRef := tb.BlobRef()
sb, err := blobserver.Receive(sto, tbRef, tb.Reader())
sb, err := blobserver.Receive(dst, tbRef, tb.Reader())
if err != nil {
t.Fatalf("Receive: %v", err)
}
@ -49,6 +46,16 @@ func TestReceive(t *testing.T) {
if sb.Ref != tbRef {
t.Fatal("wrong blob received")
}
return sb
}
func TestReceiveGood(t *testing.T) {
sto := newReplica(t, map[string]interface{}{
"backends": []interface{}{"/good-1/", "/good-2/"},
})
tb := &test.Blob{Contents: "stuff"}
sb := mustReceive(t, sto, tb)
if len(sto.replicas) != 2 {
t.Fatalf("replicas = %d; want 2", len(sto.replicas))
}
@ -61,3 +68,26 @@ func TestReceive(t *testing.T) {
}
}
}
func TestReceiveOneGoodOneFail(t *testing.T) {
sto := newReplica(t, map[string]interface{}{
"backends": []interface{}{"/good-1/", "/fail-1/"},
"minWritesForSuccess": float64(1),
})
tb := &test.Blob{Contents: "stuff"}
sb := mustReceive(t, sto, tb)
if len(sto.replicas) != 2 {
t.Fatalf("replicas = %d; want 2", len(sto.replicas))
}
for i, rep := range sto.replicas {
got, err := blobserver.StatBlob(rep, sb.Ref)
pfx := sto.replicaPrefixes[i]
if (i == 0) != (err == nil) {
t.Errorf("For replica %s, unexpected error: %v", pfx, err)
}
if err == nil && got != sb {
t.Errorf("Replica %s got %+v; want %+v", sto.replicaPrefixes[i], got, sb)
}
}
}

View File

@ -39,6 +39,9 @@ type Fetcher struct {
m map[string]*Blob // keyed by blobref string
sorted []string // blobrefs sorted
// ReceiveErr optionally returns the error to return on receive.
ReceiveErr error
// FetchErr, if non-nil, specifies the error to return on the next fetch call.
// If it returns nil, fetches proceed as normal.
FetchErr func() error
@ -117,6 +120,9 @@ func (tf *Fetcher) ReceiveBlob(br blob.Ref, source io.Reader) (blob.SizedRef, er
// it's worth the cost.
return sb, fmt.Errorf("Hash mismatch receiving blob %s", br)
}
if err := tf.ReceiveErr; err != nil {
return sb, err
}
b := &Blob{Contents: string(all)}
tf.AddBlob(b)
return blob.SizedRef{br, int64(len(all))}, nil

View File

@ -58,5 +58,8 @@ func (ld *Loader) GetStorage(prefix string) (blobserver.Storage, error) {
if strings.HasPrefix(prefix, "/good") {
return &Fetcher{}, nil
}
if strings.HasPrefix(prefix, "/fail") {
return &Fetcher{ReceiveErr: errors.New("test.Loader intentional failure for /fail storage handler")}, nil
}
panic("test.Loader.GetStorage: unrecognized prefix type")
}