15 // MockVolumes are test doubles for Volumes, used to test handlers.
16 type MockVolume struct {
17 Store map[string][]byte
18 Timestamps map[string]time.Time
19 // Bad volumes return an error for every operation.
21 // Touchable volumes' Touch() method succeeds for a locator
22 // that has been Put().
24 // Readonly volumes return an error for Put, Delete, and
27 // Gate is a "starting gate", allowing test cases to pause
28 // volume operations long enough to inspect state. Every
29 // operation (except Status) starts by receiving from
30 // Gate. Sending one value unblocks one operation; closing the
31 // channel unblocks all operations. By default, Gate is a
32 // closed channel, so all operations proceed without
33 // blocking. See trash_worker_test.go for an example.
39 // CreateMockVolume returns a non-Bad, non-Readonly, Touchable mock
41 func CreateMockVolume() *MockVolume {
42 gate := make(chan struct{})
45 Store: make(map[string][]byte),
46 Timestamps: make(map[string]time.Time),
50 called: map[string]int{},
55 // CallCount returns how many times the named method has been called.
56 func (v *MockVolume) CallCount(method string) int {
58 defer v.mutex.Unlock()
59 if c, ok := v.called[method]; !ok {
66 func (v *MockVolume) gotCall(method string) {
68 defer v.mutex.Unlock()
69 if _, ok := v.called[method]; !ok {
76 func (v *MockVolume) Compare(loc string, buf []byte) error {
80 return errors.New("Bad volume")
81 } else if block, ok := v.Store[loc]; ok {
82 if fmt.Sprintf("%x", md5.Sum(block)) != loc {
85 if bytes.Compare(buf, block) != 0 {
94 func (v *MockVolume) Get(loc string) ([]byte, error) {
98 return nil, errors.New("Bad volume")
99 } else if block, ok := v.Store[loc]; ok {
100 buf := bufs.Get(len(block))
104 return nil, os.ErrNotExist
107 func (v *MockVolume) Put(loc string, block []byte) error {
111 return errors.New("Bad volume")
114 return MethodDisabledError
120 func (v *MockVolume) Touch(loc string) error {
124 return MethodDisabledError
127 v.Timestamps[loc] = time.Now()
130 return errors.New("Touch failed")
133 func (v *MockVolume) Mtime(loc string) (time.Time, error) {
139 err = errors.New("Bad volume")
140 } else if t, ok := v.Timestamps[loc]; ok {
148 func (v *MockVolume) IndexTo(prefix string, w io.Writer) error {
151 for loc, block := range v.Store {
152 if !IsValidLocator(loc) || !strings.HasPrefix(loc, prefix) {
155 _, err := fmt.Fprintf(w, "%s+%d %d\n",
156 loc, len(block), 123456789)
164 func (v *MockVolume) Delete(loc string) error {
168 return MethodDisabledError
170 if _, ok := v.Store[loc]; ok {
171 if time.Since(v.Timestamps[loc]) < blob_signature_ttl {
177 return os.ErrNotExist
180 func (v *MockVolume) Status() *VolumeStatus {
182 for _, block := range v.Store {
183 used = used + uint64(len(block))
185 return &VolumeStatus{"/bogo", 123, 1000000 - used, used}
188 func (v *MockVolume) String() string {
189 return "[MockVolume]"
192 func (v *MockVolume) Writable() bool {