8 // A TestableVolumeManagerFactory creates a volume manager with at least two TestableVolume instances.
9 // The factory function, and the TestableVolume instances it returns, can use "t" to write
10 // logs, fail the current test, etc.
11 type TestableVolumeManagerFactory func(t TB) (*RRVolumeManager, []TestableVolume)
13 // DoHandlersWithGenericVolumeTests runs a set of handler tests with a
14 // Volume Manager comprised of TestableVolume instances.
15 // It calls factory to create a volume manager with TestableVolume
16 // instances for each test case, to avoid leaking state between tests.
17 func DoHandlersWithGenericVolumeTests(t TB, factory TestableVolumeManagerFactory) {
18 testGetBlock(t, factory, TestHash, TestBlock)
19 testGetBlock(t, factory, EmptyHash, EmptyBlock)
20 testPutRawBadDataGetBlock(t, factory, TestHash, TestBlock, []byte("baddata"))
21 testPutRawBadDataGetBlock(t, factory, EmptyHash, EmptyBlock, []byte("baddata"))
22 testPutBlock(t, factory, TestHash, TestBlock)
23 testPutBlock(t, factory, EmptyHash, EmptyBlock)
24 testPutBlockCorrupt(t, factory, TestHash, TestBlock, []byte("baddata"))
25 testPutBlockCorrupt(t, factory, EmptyHash, EmptyBlock, []byte("baddata"))
28 // Setup RRVolumeManager with TestableVolumes
29 func setupHandlersWithGenericVolumeTest(t TB, factory TestableVolumeManagerFactory) []TestableVolume {
30 vm, testableVolumes := factory(t)
33 for _, v := range testableVolumes {
38 return testableVolumes
41 // Put a block using PutRaw in just one volume and Get it using GetBlock
42 func testGetBlock(t TB, factory TestableVolumeManagerFactory, testHash string, testBlock []byte) {
43 testableVolumes := setupHandlersWithGenericVolumeTest(t, factory)
45 // Put testBlock in one volume
46 testableVolumes[1].PutRaw(testHash, testBlock)
49 buf := make([]byte, len(testBlock))
50 n, err := GetBlock(context.Background(), testHash, buf, nil)
52 t.Fatalf("Error while getting block %s", err)
54 if bytes.Compare(buf[:n], testBlock) != 0 {
55 t.Errorf("Put succeeded but Get returned %+v, expected %+v", buf[:n], testBlock)
59 // Put a bad block using PutRaw and get it.
60 func testPutRawBadDataGetBlock(t TB, factory TestableVolumeManagerFactory,
61 testHash string, testBlock []byte, badData []byte) {
62 testableVolumes := setupHandlersWithGenericVolumeTest(t, factory)
64 // Put bad data for testHash in both volumes
65 testableVolumes[0].PutRaw(testHash, badData)
66 testableVolumes[1].PutRaw(testHash, badData)
69 buf := make([]byte, BlockSize)
70 size, err := GetBlock(context.Background(), testHash, buf, nil)
72 t.Fatalf("Got %+q, expected error while getting corrupt block %v", buf[:size], testHash)
76 // Invoke PutBlock twice to ensure CompareAndTouch path is tested.
77 func testPutBlock(t TB, factory TestableVolumeManagerFactory, testHash string, testBlock []byte) {
78 setupHandlersWithGenericVolumeTest(t, factory)
81 if _, err := PutBlock(context.Background(), testBlock, testHash); err != nil {
82 t.Fatalf("Error during PutBlock: %s", err)
85 // Check that PutBlock succeeds again even after CompareAndTouch
86 if _, err := PutBlock(context.Background(), testBlock, testHash); err != nil {
87 t.Fatalf("Error during PutBlock: %s", err)
90 // Check that PutBlock stored the data as expected
91 buf := make([]byte, BlockSize)
92 size, err := GetBlock(context.Background(), testHash, buf, nil)
94 t.Fatalf("Error during GetBlock for %q: %s", testHash, err)
95 } else if bytes.Compare(buf[:size], testBlock) != 0 {
96 t.Errorf("Get response incorrect. Expected %q; found %q", testBlock, buf[:size])
100 // Put a bad block using PutRaw, overwrite it using PutBlock and get it.
101 func testPutBlockCorrupt(t TB, factory TestableVolumeManagerFactory,
102 testHash string, testBlock []byte, badData []byte) {
103 testableVolumes := setupHandlersWithGenericVolumeTest(t, factory)
105 // Put bad data for testHash in both volumes
106 testableVolumes[0].PutRaw(testHash, badData)
107 testableVolumes[1].PutRaw(testHash, badData)
109 // Check that PutBlock with good data succeeds
110 if _, err := PutBlock(context.Background(), testBlock, testHash); err != nil {
111 t.Fatalf("Error during PutBlock for %q: %s", testHash, err)
114 // Put succeeded and overwrote the badData in one volume,
115 // and Get should return the testBlock now, ignoring the bad data.
116 buf := make([]byte, BlockSize)
117 size, err := GetBlock(context.Background(), testHash, buf, nil)
119 t.Fatalf("Error during GetBlock for %q: %s", testHash, err)
120 } else if bytes.Compare(buf[:size], testBlock) != 0 {
121 t.Errorf("Get response incorrect. Expected %q; found %q", testBlock, buf[:size])