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