github.com/lbryio/lbcd@v0.22.119/database/ffldb/mockfile_test.go (about) 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)