12 func TempUnixVolume(t *testing.T, queue chan *IORequest) UnixVolume {
13 d, err := ioutil.TempDir("", "volume_test")
17 return MakeUnixVolume(d, queue)
20 func _teardown(v UnixVolume) {
27 // store writes a Keep block directly into a UnixVolume, for testing
28 // UnixVolume methods.
30 func _store(t *testing.T, vol UnixVolume, filename string, block []byte) {
31 blockdir := fmt.Sprintf("%s/%s", vol.root, filename[:3])
32 if err := os.MkdirAll(blockdir, 0755); err != nil {
36 blockpath := fmt.Sprintf("%s/%s", blockdir, filename)
37 if f, err := os.Create(blockpath); err == nil {
45 func TestGet(t *testing.T) {
46 v := TempUnixVolume(t, nil)
48 _store(t, v, TEST_HASH, TEST_BLOCK)
50 buf, err := v.Get(TEST_HASH)
54 if bytes.Compare(buf, TEST_BLOCK) != 0 {
55 t.Errorf("expected %s, got %s", string(TEST_BLOCK), string(buf))
59 func TestGetNotFound(t *testing.T) {
60 v := TempUnixVolume(t, nil)
62 _store(t, v, TEST_HASH, TEST_BLOCK)
64 buf, err := v.Get(TEST_HASH_2)
66 case os.IsNotExist(err):
69 t.Errorf("Read should have failed, returned %s", string(buf))
71 t.Errorf("Read expected ErrNotExist, got: %s", err)
75 func TestPut(t *testing.T) {
76 v := TempUnixVolume(t, nil)
79 err := v.Put(TEST_HASH, TEST_BLOCK)
83 p := fmt.Sprintf("%s/%s/%s", v.root, TEST_HASH[:3], TEST_HASH)
84 if buf, err := ioutil.ReadFile(p); err != nil {
86 } else if bytes.Compare(buf, TEST_BLOCK) != 0 {
87 t.Errorf("Write should have stored %s, did store %s",
88 string(TEST_BLOCK), string(buf))
92 func TestPutBadVolume(t *testing.T) {
93 v := TempUnixVolume(t, nil)
97 err := v.Put(TEST_HASH, TEST_BLOCK)
99 t.Error("Write should have failed")
103 // Serialization tests: launch a bunch of concurrent
105 // TODO(twp): show that the underlying Read/Write operations executed
106 // serially and not concurrently. The easiest way to do this is
107 // probably to activate verbose or debug logging, capture log output
108 // and examine it to confirm that Reads and Writes did not overlap.
110 // TODO(twp): a proper test of I/O serialization requires that a
111 // second request start while the first one is still underway.
112 // Guaranteeing that the test behaves this way requires some tricky
113 // synchronization and mocking. For now we'll just launch a bunch of
114 // requests simultaenously in goroutines and demonstrate that they
115 // return accurate results.
117 func TestGetSerialized(t *testing.T) {
118 v := TempUnixVolume(t, make(chan *IORequest))
121 _store(t, v, TEST_HASH, TEST_BLOCK)
122 _store(t, v, TEST_HASH_2, TEST_BLOCK_2)
123 _store(t, v, TEST_HASH_3, TEST_BLOCK_3)
125 sem := make(chan int)
126 go func(sem chan int) {
127 buf, err := v.Get(TEST_HASH)
129 t.Errorf("err1: %v", err)
131 if bytes.Compare(buf, TEST_BLOCK) != 0 {
132 t.Errorf("buf should be %s, is %s", string(TEST_BLOCK), string(buf))
137 go func(sem chan int) {
138 buf, err := v.Get(TEST_HASH_2)
140 t.Errorf("err2: %v", err)
142 if bytes.Compare(buf, TEST_BLOCK_2) != 0 {
143 t.Errorf("buf should be %s, is %s", string(TEST_BLOCK_2), string(buf))
148 go func(sem chan int) {
149 buf, err := v.Get(TEST_HASH_3)
151 t.Errorf("err3: %v", err)
153 if bytes.Compare(buf, TEST_BLOCK_3) != 0 {
154 t.Errorf("buf should be %s, is %s", string(TEST_BLOCK_3), string(buf))
159 // Wait for all goroutines to finish
160 for done := 0; done < 2; {
165 func TestPutSerialized(t *testing.T) {
166 v := TempUnixVolume(t, make(chan *IORequest))
169 sem := make(chan int)
170 go func(sem chan int) {
171 err := v.Put(TEST_HASH, TEST_BLOCK)
173 t.Errorf("err1: %v", err)
178 go func(sem chan int) {
179 err := v.Put(TEST_HASH_2, TEST_BLOCK_2)
181 t.Errorf("err2: %v", err)
186 go func(sem chan int) {
187 err := v.Put(TEST_HASH_3, TEST_BLOCK_3)
189 t.Errorf("err3: %v", err)
194 // Wait for all goroutines to finish
195 for done := 0; done < 2; {
199 // Double check that we actually wrote the blocks we expected to write.
200 buf, err := v.Get(TEST_HASH)
202 t.Errorf("Get #1: %v", err)
204 if bytes.Compare(buf, TEST_BLOCK) != 0 {
205 t.Errorf("Get #1: expected %s, got %s", string(TEST_BLOCK), string(buf))
208 buf, err = v.Get(TEST_HASH_2)
210 t.Errorf("Get #2: %v", err)
212 if bytes.Compare(buf, TEST_BLOCK_2) != 0 {
213 t.Errorf("Get #2: expected %s, got %s", string(TEST_BLOCK_2), string(buf))
216 buf, err = v.Get(TEST_HASH_3)
218 t.Errorf("Get #3: %v", err)
220 if bytes.Compare(buf, TEST_BLOCK_3) != 0 {
221 t.Errorf("Get #3: expected %s, got %s", string(TEST_BLOCK_3), string(buf))
225 func TestIsFull(t *testing.T) {
226 v := TempUnixVolume(t, nil)
229 full_path := v.root + "/full"
230 now := fmt.Sprintf("%d", time.Now().Unix())
231 os.Symlink(now, full_path)
233 t.Errorf("%s: claims not to be full", v)
237 // Test with an expired /full link.
238 expired := fmt.Sprintf("%d", time.Now().Unix()-3605)
239 os.Symlink(expired, full_path)
241 t.Errorf("%s: should no longer be full", v)