7329: It appears that UnixVolume -> Compare method is falling in infinite loop due...
[arvados.git] / services / keepstore / keepstore_integration_unix_volume_test.go
1 package main
2
3 import (
4         "bytes"
5         "os"
6         "testing"
7
8         "git.curoverse.com/arvados.git/sdk/go/arvadostest"
9 )
10
11 func SetupKeepStoreUnixVolumeIntegrationTest(t *testing.T) {
12         os.Setenv("ARVADOS_API_HOST_INSECURE", "true")
13
14         // Set up Keep unix volumes
15         KeepVM = MakeTestUnixVolumeManager(t, 2)
16         defer KeepVM.Close()
17
18         // Start api and keep servers
19         arvadostest.StartAPI()
20         arvadostest.StartKeep()
21 }
22
23 // MakeTestUnixVolumeManager returns a RRVolumeManager
24 // with the specified number of UnixVolumes.
25 var testableUnixVols []*TestableUnixVolume
26
27 func MakeTestUnixVolumeManager(t *testing.T, numVolumes int) VolumeManager {
28         vols := make([]Volume, numVolumes)
29         testableUnixVols = make([]*TestableUnixVolume, numVolumes)
30
31         for i := range vols {
32                 v := NewTestableUnixVolume(t, false, false)
33                 vols[i] = v
34                 testableUnixVols[i] = v
35         }
36         return MakeRRVolumeManager(vols)
37 }
38
39 // Put TestBlock and Get it
40 func TestPutTestBlock(t *testing.T) {
41         SetupKeepStoreUnixVolumeIntegrationTest(t)
42
43         // Check that PutBlock succeeds
44         if err := PutBlock(TestBlock, TestHash); err != nil {
45                 t.Fatalf("Error during PutBlock: %s", err)
46         }
47
48         // Check that PutBlock succeeds again even after CompareAndTouch
49         if err := PutBlock(TestBlock, TestHash); err != nil {
50                 t.Fatalf("Error during PutBlock: %s", err)
51         }
52
53         // Check that PutBlock stored the data as expected
54         buf, err := GetBlock(TestHash)
55         if err != nil {
56                 t.Fatalf("Error during GetBlock for %q: %s", TestHash, err)
57         } else if bytes.Compare(buf, TestBlock) != 0 {
58                 t.Errorf("Get response incorrect. Expected %q; found %q", TestBlock, buf)
59         }
60 }
61
62 // UnixVolume -> Compare is falling in infinite loop since EOF is not being
63 // returned by reader.Read() for empty block resulting in issue #7329.
64 // Hence invoke PutBlock twice to test that path involving CompareAndTouch
65 func TestPutEmptyBlock(t *testing.T) {
66         SetupKeepStoreUnixVolumeIntegrationTest(t)
67
68         // Check that PutBlock succeeds
69         if err := PutBlock(EmptyBlock, EmptyHash); err != nil {
70                 t.Fatalf("Error during PutBlock: %s", err)
71         }
72
73         // Check that PutBlock succeeds again even after CompareAndTouch
74         // With #7329 unresovled, this falls in infinite loop in UnixVolume -> Compare method
75         if err := PutBlock(EmptyBlock, EmptyHash); err != nil {
76                 t.Fatalf("Error during PutBlock: %s", err)
77         }
78
79         // Check that PutBlock stored the data as expected
80         buf, err := GetBlock(EmptyHash)
81         if err != nil {
82                 t.Fatalf("Error during GetBlock for %q: %s", EmptyHash, err)
83         } else if bytes.Compare(buf, EmptyBlock) != 0 {
84                 t.Errorf("Get response incorrect. Expected %q; found %q", EmptyBlock, buf)
85         }
86 }
87
88 // PutRaw EmptyHash with bad data (which bypasses hash check)
89 // and then invoke PutBlock with the correct EmptyBlock.
90 // Put should succeed and next Get should return EmptyBlock
91 func TestPutEmptyBlockDiskHashError(t *testing.T) {
92         SetupKeepStoreUnixVolumeIntegrationTest(t)
93
94         badEmptyBlock := []byte("verybaddata")
95
96         // Put bad data for EmptyHash in both volumes
97         testableUnixVols[0].PutRaw(EmptyHash, badEmptyBlock)
98         testableUnixVols[1].PutRaw(EmptyHash, badEmptyBlock)
99
100         // Check that PutBlock with good data succeeds
101         if err := PutBlock(EmptyBlock, EmptyHash); err != nil {
102                 t.Fatalf("Error during PutBlock for %q: %s", EmptyHash, err)
103         }
104
105         // Put succeeded and overwrote the badEmptyBlock in one volume,
106         // and Get should return the EmptyBlock now, ignoring the bad data.
107         buf, err := GetBlock(EmptyHash)
108         if err != nil {
109                 t.Fatalf("Error during GetBlock for %q: %s", EmptyHash, err)
110         } else if bytes.Compare(buf, EmptyBlock) != 0 {
111                 t.Errorf("Get response incorrect. Expected %q; found %q", TestBlock, buf)
112         }
113 }