17 type TestableUnixVolume struct {
22 func NewTestableUnixVolume(t *testing.T, serialize bool, readonly bool) *TestableUnixVolume {
23 d, err := ioutil.TempDir("", "volume_test")
27 var locker sync.Locker
29 locker = &sync.Mutex{}
31 return &TestableUnixVolume{
32 UnixVolume: UnixVolume{
41 // PutRaw writes a Keep block directly into a UnixVolume, even if
42 // the volume is readonly.
43 func (v *TestableUnixVolume) PutRaw(locator string, data []byte) {
44 defer func(orig bool) {
48 err := v.Put(locator, data)
54 func (v *TestableUnixVolume) TouchWithDate(locator string, lastPut time.Time) {
55 err := syscall.Utime(v.blockPath(locator), &syscall.Utimbuf{lastPut.Unix(), lastPut.Unix()})
61 func (v *TestableUnixVolume) Teardown() {
62 if err := os.RemoveAll(v.root); err != nil {
67 func TestUnixVolumeWithGenericTests(t *testing.T) {
68 DoGenericVolumeTests(t, func(t *testing.T) TestableVolume {
69 return NewTestableUnixVolume(t, false, false)
73 func TestUnixReadOnlyVolumeWithGenericTests(t *testing.T) {
74 DoGenericReadOnlyVolumeTests(t, func(t *testing.T) TestableVolume {
75 return NewTestableUnixVolume(t, false, true)
79 func TestGetNotFound(t *testing.T) {
80 v := NewTestableUnixVolume(t, false, false)
82 v.Put(TEST_HASH, TEST_BLOCK)
84 buf, err := v.Get(TEST_HASH_2)
86 case os.IsNotExist(err):
89 t.Errorf("Read should have failed, returned %s", string(buf))
91 t.Errorf("Read expected ErrNotExist, got: %s", err)
95 func TestPut(t *testing.T) {
96 v := NewTestableUnixVolume(t, false, false)
99 err := v.Put(TEST_HASH, TEST_BLOCK)
103 p := fmt.Sprintf("%s/%s/%s", v.root, TEST_HASH[:3], TEST_HASH)
104 if buf, err := ioutil.ReadFile(p); err != nil {
106 } else if bytes.Compare(buf, TEST_BLOCK) != 0 {
107 t.Errorf("Write should have stored %s, did store %s",
108 string(TEST_BLOCK), string(buf))
112 func TestPutBadVolume(t *testing.T) {
113 v := NewTestableUnixVolume(t, false, false)
116 os.Chmod(v.root, 000)
117 err := v.Put(TEST_HASH, TEST_BLOCK)
119 t.Error("Write should have failed")
123 func TestUnixVolumeReadonly(t *testing.T) {
124 v := NewTestableUnixVolume(t, false, true)
127 v.PutRaw(TEST_HASH, TEST_BLOCK)
129 _, err := v.Get(TEST_HASH)
131 t.Errorf("got err %v, expected nil", err)
134 err = v.Put(TEST_HASH, TEST_BLOCK)
135 if err != MethodDisabledError {
136 t.Errorf("got err %v, expected MethodDisabledError", err)
139 err = v.Touch(TEST_HASH)
140 if err != MethodDisabledError {
141 t.Errorf("got err %v, expected MethodDisabledError", err)
144 err = v.Delete(TEST_HASH)
145 if err != MethodDisabledError {
146 t.Errorf("got err %v, expected MethodDisabledError", err)
150 func TestIsFull(t *testing.T) {
151 v := NewTestableUnixVolume(t, false, false)
154 full_path := v.root + "/full"
155 now := fmt.Sprintf("%d", time.Now().Unix())
156 os.Symlink(now, full_path)
158 t.Errorf("%s: claims not to be full", v)
162 // Test with an expired /full link.
163 expired := fmt.Sprintf("%d", time.Now().Unix()-3605)
164 os.Symlink(expired, full_path)
166 t.Errorf("%s: should no longer be full", v)
170 func TestNodeStatus(t *testing.T) {
171 v := NewTestableUnixVolume(t, false, false)
174 // Get node status and make a basic sanity check.
175 volinfo := v.Status()
176 if volinfo.MountPoint != v.root {
177 t.Errorf("GetNodeStatus mount_point %s, expected %s", volinfo.MountPoint, v.root)
179 if volinfo.DeviceNum == 0 {
180 t.Errorf("uninitialized device_num in %v", volinfo)
182 if volinfo.BytesFree == 0 {
183 t.Errorf("uninitialized bytes_free in %v", volinfo)
185 if volinfo.BytesUsed == 0 {
186 t.Errorf("uninitialized bytes_used in %v", volinfo)
190 func TestUnixVolumeGetFuncWorkerError(t *testing.T) {
191 v := NewTestableUnixVolume(t, false, false)
194 v.Put(TEST_HASH, TEST_BLOCK)
195 mockErr := errors.New("Mock error")
196 err := v.getFunc(v.blockPath(TEST_HASH), func(rdr io.Reader) error {
200 t.Errorf("Got %v, expected %v", err, mockErr)
204 func TestUnixVolumeGetFuncFileError(t *testing.T) {
205 v := NewTestableUnixVolume(t, false, false)
209 err := v.getFunc(v.blockPath(TEST_HASH), func(rdr io.Reader) error {
214 t.Errorf("Expected error opening non-existent file")
217 t.Errorf("Worker func should not have been called")
221 func TestUnixVolumeGetFuncWorkerWaitsOnMutex(t *testing.T) {
222 v := NewTestableUnixVolume(t, false, false)
225 v.Put(TEST_HASH, TEST_BLOCK)
227 mtx := NewMockMutex()
230 funcCalled := make(chan struct{})
231 go v.getFunc(v.blockPath(TEST_HASH), func(rdr io.Reader) error {
232 funcCalled <- struct{}{}
236 case mtx.AllowLock <- struct{}{}:
238 t.Fatal("Function was called before mutex was acquired")
239 case <-time.After(5 * time.Second):
240 t.Fatal("Timed out before mutex was acquired")
244 case mtx.AllowUnlock <- struct{}{}:
245 t.Fatal("Mutex was released before function was called")
246 case <-time.After(5 * time.Second):
247 t.Fatal("Timed out waiting for funcCalled")
250 case mtx.AllowUnlock <- struct{}{}:
251 case <-time.After(5 * time.Second):
252 t.Fatal("Timed out waiting for getFunc() to release mutex")
256 func TestUnixVolumeCompare(t *testing.T) {
257 v := NewTestableUnixVolume(t, false, false)
260 v.Put(TEST_HASH, TEST_BLOCK)
261 err := v.Compare(TEST_HASH, TEST_BLOCK)
263 t.Errorf("Got err %q, expected nil", err)
266 err = v.Compare(TEST_HASH, []byte("baddata"))
267 if err != CollisionError {
268 t.Errorf("Got err %q, expected %q", err, CollisionError)
271 v.Put(TEST_HASH, []byte("baddata"))
272 err = v.Compare(TEST_HASH, TEST_BLOCK)
273 if err != DiskHashError {
274 t.Errorf("Got err %q, expected %q", err, DiskHashError)
277 p := fmt.Sprintf("%s/%s/%s", v.root, TEST_HASH[:3], TEST_HASH)
279 err = v.Compare(TEST_HASH, TEST_BLOCK)
280 if err == nil || strings.Index(err.Error(), "permission denied") < 0 {
281 t.Errorf("Got err %q, expected %q", err, "permission denied")