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.
5 // This file is part of the ffldb package rather than the ffldb_test package as
6 // it is part of the whitebox testing.
16 // Errors used for the mock file.
18 // errMockFileClosed is used to indicate a mock file is closed.
19 errMockFileClosed = errors.New("file closed")
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")
25 // errSyncFail is used to indicate simulated sync failure.
26 errSyncFail = errors.New("simulated sync failure")
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 {
40 // Close closes the mock file without releasing any data associated with it.
41 // This allows it to be "reopened" without losing the data.
43 // This is part of the filer implementation.
44 func (f *mockFile) Close() error {
49 return errMockFileClosed
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
60 // This is part of the filer implementation.
61 func (f *mockFile) ReadAt(b []byte, off int64) (int, error) {
66 return 0, errMockFileClosed
68 maxSize := int64(len(f.data))
69 if f.maxSize > -1 && maxSize > f.maxSize {
72 if off < 0 || off > maxSize {
73 return 0, errInvalidOffset
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
83 copy(b, f.data[off:off+numToRead])
84 if numToRead < int64(len(b)) {
85 return int(numToRead), io.EOF
87 return int(numToRead), nil
90 // Truncate changes the size of the mock file.
92 // This is part of the filer implementation.
93 func (f *mockFile) Truncate(size int64) error {
98 return errMockFileClosed
100 maxSize := int64(len(f.data))
101 if f.maxSize > -1 && maxSize > f.maxSize {
105 return errInvalidOffset
108 f.data = f.data[:size]
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
116 // This is part of the filer implementation.
117 func (f *mockFile) WriteAt(b []byte, off int64) (int, error) {
122 return 0, errMockFileClosed
126 maxSize = 100 * 1024 // 100KiB
128 if off < 0 || off > maxSize {
129 return 0, errInvalidOffset
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
137 if off+numToWrite > int64(len(f.data)) {
138 newData := make([]byte, off+numToWrite)
139 copy(newData, f.data)
143 copy(f.data[off:], b[:numToWrite])
144 if numToWrite < int64(len(b)) {
145 return int(numToWrite), io.EOF
147 return int(numToWrite), nil
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.
153 // This is part of the filer implementation.
154 func (f *mockFile) Sync() error {
162 // Ensure the mockFile type implements the filer interface.
163 var _ filer = (*mockFile)(nil)