Merge branch 'master' into 7241-azure-blob-volume
authorTom Clegg <tom@curoverse.com>
Tue, 29 Sep 2015 18:22:22 +0000 (14:22 -0400)
committerTom Clegg <tom@curoverse.com>
Tue, 29 Sep 2015 18:26:41 +0000 (14:26 -0400)
Conflicts:
services/keepstore/volume_generic_test.go
services/keepstore/handlers_with_generic_volume_test.go

1  2 
services/keepstore/collision.go
services/keepstore/handlers_with_generic_volume_test.go
services/keepstore/keepstore.go
services/keepstore/keepstore_test.go
services/keepstore/volume_generic_test.go

Simple merge
index 0000000000000000000000000000000000000000,90094f311722c1cdd71ba94f51d87a9f867a8b57..9f31f5f6fe5f31d38745046f7a771982f6b2ad00
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,119 +1,119 @@@
 -      if err := PutBlock(testBlock, testHash); err != nil {
+ package main
+ import (
+       "bytes"
+       "testing"
+ )
+ // A TestableVolumeManagerFactory creates a volume manager with at least two TestableVolume instances.
+ // The factory function, and the TestableVolume instances it returns, can use "t" to write
+ // logs, fail the current test, etc.
+ type TestableVolumeManagerFactory func(t *testing.T) (*RRVolumeManager, []TestableVolume)
+ // DoHandlersWithGenericVolumeTests runs a set of handler tests with a
+ // Volume Manager comprised of TestableVolume instances.
+ // It calls factory to create a volume manager with TestableVolume
+ // instances for each test case, to avoid leaking state between tests.
+ func DoHandlersWithGenericVolumeTests(t *testing.T, factory TestableVolumeManagerFactory) {
+       testGetBlock(t, factory, TestHash, TestBlock)
+       testGetBlock(t, factory, EmptyHash, EmptyBlock)
+       testPutRawBadDataGetBlock(t, factory, TestHash, TestBlock, []byte("baddata"))
+       testPutRawBadDataGetBlock(t, factory, EmptyHash, EmptyBlock, []byte("baddata"))
+       testPutBlock(t, factory, TestHash, TestBlock)
+       testPutBlock(t, factory, EmptyHash, EmptyBlock)
+       testPutBlockCorrupt(t, factory, TestHash, TestBlock, []byte("baddata"))
+       testPutBlockCorrupt(t, factory, EmptyHash, EmptyBlock, []byte("baddata"))
+ }
+ // Setup RRVolumeManager with TestableVolumes
+ func setupHandlersWithGenericVolumeTest(t *testing.T, factory TestableVolumeManagerFactory) []TestableVolume {
+       vm, testableVolumes := factory(t)
+       KeepVM = vm
+       for _, v := range testableVolumes {
+               defer v.Teardown()
+       }
+       defer KeepVM.Close()
+       return testableVolumes
+ }
+ // Put a block using PutRaw in just one volume and Get it using GetBlock
+ func testGetBlock(t *testing.T, factory TestableVolumeManagerFactory, testHash string, testBlock []byte) {
+       testableVolumes := setupHandlersWithGenericVolumeTest(t, factory)
+       // Put testBlock in one volume
+       testableVolumes[1].PutRaw(testHash, testBlock)
+       // Get should pass
+       buf, err := GetBlock(testHash)
+       if err != nil {
+               t.Fatalf("Error while getting block %s", err)
+       }
+       if bytes.Compare(buf, testBlock) != 0 {
+               t.Errorf("Put succeeded but Get returned %+v, expected %+v", buf, testBlock)
+       }
+ }
+ // Put a bad block using PutRaw and get it.
+ func testPutRawBadDataGetBlock(t *testing.T, factory TestableVolumeManagerFactory,
+       testHash string, testBlock []byte, badData []byte) {
+       testableVolumes := setupHandlersWithGenericVolumeTest(t, factory)
+       // Put bad data for testHash in both volumes
+       testableVolumes[0].PutRaw(testHash, badData)
+       testableVolumes[1].PutRaw(testHash, badData)
+       // Get should fail
+       _, err := GetBlock(testHash)
+       if err == nil {
+               t.Fatalf("Expected error while getting corrupt block %v", testHash)
+       }
+ }
+ // Invoke PutBlock twice to ensure CompareAndTouch path is tested.
+ func testPutBlock(t *testing.T, factory TestableVolumeManagerFactory, testHash string, testBlock []byte) {
+       setupHandlersWithGenericVolumeTest(t, factory)
+       // PutBlock
 -      if err := PutBlock(testBlock, testHash); err != nil {
++      if _, err := PutBlock(testBlock, testHash); err != nil {
+               t.Fatalf("Error during PutBlock: %s", err)
+       }
+       // Check that PutBlock succeeds again even after CompareAndTouch
 -      if err := PutBlock(testBlock, testHash); err != nil {
++      if _, err := PutBlock(testBlock, testHash); err != nil {
+               t.Fatalf("Error during PutBlock: %s", err)
+       }
+       // Check that PutBlock stored the data as expected
+       buf, err := GetBlock(testHash)
+       if err != nil {
+               t.Fatalf("Error during GetBlock for %q: %s", testHash, err)
+       } else if bytes.Compare(buf, testBlock) != 0 {
+               t.Errorf("Get response incorrect. Expected %q; found %q", testBlock, buf)
+       }
+ }
+ // Put a bad block using PutRaw, overwrite it using PutBlock and get it.
+ func testPutBlockCorrupt(t *testing.T, factory TestableVolumeManagerFactory,
+       testHash string, testBlock []byte, badData []byte) {
+       testableVolumes := setupHandlersWithGenericVolumeTest(t, factory)
+       // Put bad data for testHash in both volumes
+       testableVolumes[0].PutRaw(testHash, badData)
+       testableVolumes[1].PutRaw(testHash, badData)
+       // Check that PutBlock with good data succeeds
++      if _, err := PutBlock(testBlock, testHash); err != nil {
+               t.Fatalf("Error during PutBlock for %q: %s", testHash, err)
+       }
+       // Put succeeded and overwrote the badData in one volume,
+       // and Get should return the testBlock now, ignoring the bad data.
+       buf, err := GetBlock(testHash)
+       if err != nil {
+               t.Fatalf("Error during GetBlock for %q: %s", testHash, err)
+       } else if bytes.Compare(buf, testBlock) != 0 {
+               t.Errorf("Get response incorrect. Expected %q; found %q", testBlock, buf)
+       }
+ }
Simple merge
Simple merge
index 503e6b9a58e4e16c2fb47b71b80547a77e4d1d8d,c08c3f5f0007ac483486cb01d1e6a4bd68253d42..6dca74eaf2100e7003f9727041dbe07d999d632a
@@@ -170,15 -181,15 +181,15 @@@ func testPutBlockWithDifferentContent(
        if putErr == nil {
                // Put must not return a nil error unless it has
                // overwritten the existing data.
-               if bytes.Compare(buf, TestBlock2) != 0 {
-                       t.Errorf("Put succeeded but Get returned %+q, expected %+q", buf, TestBlock2)
+               if bytes.Compare(buf, testDataB) != 0 {
 -                      t.Errorf("Put succeeded but Get returned %+v, expected %+v", buf, testDataB)
++                      t.Errorf("Put succeeded but Get returned %+q, expected %+q", buf, testDataB)
                }
        } else {
                // It is permissible for Put to fail, but it must
                // leave us with either the original data, the new
                // data, or nothing at all.
-               if getErr == nil && bytes.Compare(buf, TestBlock) != 0 && bytes.Compare(buf, TestBlock2) != 0 {
-                       t.Errorf("Put failed but Get returned %+q, which is neither %+q nor %+q", buf, TestBlock, TestBlock2)
+               if getErr == nil && bytes.Compare(buf, testDataA) != 0 && bytes.Compare(buf, testDataB) != 0 {
 -                      t.Errorf("Put failed but Get returned %+v, which is neither %+v nor %+v", buf, testDataA, testDataB)
++                      t.Errorf("Put failed but Get returned %+q, which is neither %+q nor %+q", buf, testDataA, testDataB)
                }
        }
        if getErr == nil {