OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / database / ffldb / mockfile_test.go
1 // Copyright (c) 2015-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 // This file is part of the ffldb package rather than the ffldb_test package as
6 // it is part of the whitebox testing.
7
8 package ffldb
9
10 import (
11         "errors"
12         "io"
13         "sync"
14 )
15
16 // Errors used for the mock file.
17 var (
18         // errMockFileClosed is used to indicate a mock file is closed.
19         errMockFileClosed = errors.New("file closed")
20
21         // errInvalidOffset is used to indicate an offset that is out of range
22         // for the file was provided.
23         errInvalidOffset = errors.New("invalid offset")
24
25         // errSyncFail is used to indicate simulated sync failure.
26         errSyncFail = errors.New("simulated sync failure")
27 )
28
29 // mockFile implements the filer interface and used in order to force failures
30 // the database code related to reading and writing from the flat block files.
31 // A maxSize of -1 is unlimited.
32 type mockFile struct {
33         sync.RWMutex
34         maxSize      int64
35         data         []byte
36         forceSyncErr bool
37         closed       bool
38 }
39
40 // Close closes the mock file without releasing any data associated with it.
41 // This allows it to be "reopened" without losing the data.
42 //
43 // This is part of the filer implementation.
44 func (f *mockFile) Close() error {
45         f.Lock()
46         defer f.Unlock()
47
48         if f.closed {
49                 return errMockFileClosed
50         }
51         f.closed = true
52         return nil
53 }
54
55 // ReadAt reads len(b) bytes from the mock file starting at byte offset off. It
56 // returns the number of bytes read and the error, if any.  ReadAt always
57 // returns a non-nil error when n < len(b). At end of file, that error is
58 // io.EOF.
59 //
60 // This is part of the filer implementation.
61 func (f *mockFile) ReadAt(b []byte, off int64) (int, error) {
62         f.RLock()
63         defer f.RUnlock()
64
65         if f.closed {
66                 return 0, errMockFileClosed
67         }
68         maxSize := int64(len(f.data))
69         if f.maxSize > -1 && maxSize > f.maxSize {
70                 maxSize = f.maxSize
71         }
72         if off < 0 || off > maxSize {
73                 return 0, errInvalidOffset
74         }
75
76         // Limit to the max size field, if set.
77         numToRead := int64(len(b))
78         endOffset := off + numToRead
79         if endOffset > maxSize {
80                 numToRead = maxSize - off
81         }
82
83         copy(b, f.data[off:off+numToRead])
84         if numToRead < int64(len(b)) {
85                 return int(numToRead), io.EOF
86         }
87         return int(numToRead), nil
88 }
89
90 // Truncate changes the size of the mock file.
91 //
92 // This is part of the filer implementation.
93 func (f *mockFile) Truncate(size int64) error {
94         f.Lock()
95         defer f.Unlock()
96
97         if f.closed {
98                 return errMockFileClosed
99         }
100         maxSize := int64(len(f.data))
101         if f.maxSize > -1 && maxSize > f.maxSize {
102                 maxSize = f.maxSize
103         }
104         if size > maxSize {
105                 return errInvalidOffset
106         }
107
108         f.data = f.data[:size]
109         return nil
110 }
111
112 // Write writes len(b) bytes to the mock file. It returns the number of bytes
113 // written and an error, if any.  Write returns a non-nil error any time
114 // n != len(b).
115 //
116 // This is part of the filer implementation.
117 func (f *mockFile) WriteAt(b []byte, off int64) (int, error) {
118         f.Lock()
119         defer f.Unlock()
120
121         if f.closed {
122                 return 0, errMockFileClosed
123         }
124         maxSize := f.maxSize
125         if maxSize < 0 {
126                 maxSize = 100 * 1024 // 100KiB
127         }
128         if off < 0 || off > maxSize {
129                 return 0, errInvalidOffset
130         }
131
132         // Limit to the max size field, if set, and grow the slice if needed.
133         numToWrite := int64(len(b))
134         if off+numToWrite > maxSize {
135                 numToWrite = maxSize - off
136         }
137         if off+numToWrite > int64(len(f.data)) {
138                 newData := make([]byte, off+numToWrite)
139                 copy(newData, f.data)
140                 f.data = newData
141         }
142
143         copy(f.data[off:], b[:numToWrite])
144         if numToWrite < int64(len(b)) {
145                 return int(numToWrite), io.EOF
146         }
147         return int(numToWrite), nil
148 }
149
150 // Sync doesn't do anything for mock files.  However, it will return an error if
151 // the mock file's forceSyncErr flag is set.
152 //
153 // This is part of the filer implementation.
154 func (f *mockFile) Sync() error {
155         if f.forceSyncErr {
156                 return errSyncFail
157         }
158
159         return nil
160 }
161
162 // Ensure the mockFile type implements the filer interface.
163 var _ filer = (*mockFile)(nil)