github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/digest/reader_test.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package digest 22 23 import ( 24 "errors" 25 "os" 26 "testing" 27 28 "github.com/stretchr/testify/require" 29 ) 30 31 const ( 32 testReaderBufferSize = 10 33 ) 34 35 func createTestFdWithDigestReader(t *testing.T) (*fdWithDigestReader, *os.File, *mockDigest) { 36 fd, md := createTestFdWithDigest(t) 37 reader := NewFdWithDigestReader(testReaderBufferSize).(*fdWithDigestReader) 38 reader.readerWithDigest.(*readerWithDigest).digest = md 39 reader.Reset(fd) 40 return reader, fd, md 41 } 42 43 func createTestFdWithDigestContentsReader(t *testing.T) (*fdWithDigestContentsReader, *os.File, *mockDigest) { 44 fdr, fd, md := createTestFdWithDigestReader(t) 45 reader := NewFdWithDigestContentsReader(testReaderBufferSize).(*fdWithDigestContentsReader) 46 reader.FdWithDigestReader = fdr 47 return reader, fd, md 48 } 49 50 func bufferFor(t *testing.T, fd *os.File) []byte { 51 stat, err := fd.Stat() 52 require.NoError(t, err) 53 size := int(stat.Size()) 54 return make([]byte, size) 55 } 56 57 func TestFdWithDigestReaderReset(t *testing.T) { 58 reader, _, _ := createTestFdWithDigestReader(t) 59 require.NotNil(t, reader.Fd()) 60 reader.Reset(nil) 61 require.Nil(t, reader.Fd()) 62 } 63 64 func TestFdWithDigestReadBytesFileReadError(t *testing.T) { 65 reader, fd, _ := createTestFdWithDigestReader(t) 66 defer func() { 67 fd.Close() 68 os.Remove(fd.Name()) 69 }() 70 71 toRead := make([]byte, 1) 72 _, err := reader.Read(toRead) 73 require.Error(t, err) 74 } 75 76 func TestFdWithDigestReadBytesDigestWriteError(t *testing.T) { 77 reader, fd, md := createTestFdWithDigestReader(t) 78 defer func() { 79 fd.Close() 80 os.Remove(fd.Name()) 81 }() 82 83 b := make([]byte, 1) 84 _, err := fd.Write(b) 85 require.NoError(t, err) 86 _, err = fd.Seek(-1, 1) 87 require.NoError(t, err) 88 89 md.err = errors.New("foo") 90 reader.Reset(fd) 91 _, err = reader.Read(b) 92 require.Equal(t, "foo", err.Error()) 93 } 94 95 func TestFdWithDigestReadBytesSuccess(t *testing.T) { 96 reader, fd, md := createTestFdWithDigestReader(t) 97 defer func() { 98 fd.Close() 99 os.Remove(fd.Name()) 100 }() 101 102 b := []byte{0x1} 103 fd.Write(b) 104 fd.Seek(-1, 1) 105 106 n, err := reader.Read(b) 107 require.NoError(t, err) 108 require.Equal(t, 1, n) 109 require.Equal(t, b, md.b) 110 } 111 112 func TestFdWithDigestReadBytesBuffered(t *testing.T) { 113 reader, fd, md := createTestFdWithDigestReader(t) 114 defer func() { 115 fd.Close() 116 os.Remove(fd.Name()) 117 }() 118 119 b := make([]byte, 154) 120 b[153] = byte(1) 121 fd.Write(b) 122 fd.Seek(0, 0) 123 124 for _, readSize := range []int{27, 127} { 125 toRead := make([]byte, readSize) 126 n, err := reader.Read(toRead) 127 require.NoError(t, err) 128 require.Equal(t, readSize, n) 129 } 130 131 require.Equal(t, b, md.b) 132 } 133 134 func TestFdWithDigestReadAllFileReadError(t *testing.T) { 135 reader, fd, _ := createTestFdWithDigestReader(t) 136 defer func() { 137 fd.Close() 138 os.Remove(fd.Name()) 139 }() 140 141 reader.Reset(nil) 142 buf := bufferFor(t, fd) 143 _, err := reader.ReadAllAndValidate(buf, 0) 144 require.Error(t, err) 145 } 146 147 func testFdWithDigestReadAllValidation(t *testing.T, expectedDigest uint32, expectedErr error) { 148 reader, fd, md := createTestFdWithDigestReader(t) 149 defer func() { 150 fd.Close() 151 os.Remove(fd.Name()) 152 }() 153 154 b := []byte{0x1} 155 fd.Write(b) 156 fd.Seek(-1, 1) 157 158 md.digest = 1 159 buf := bufferFor(t, fd) 160 _, err := reader.ReadAllAndValidate(buf, expectedDigest) 161 require.Equal(t, expectedErr, err) 162 } 163 164 func TestFdWithDigestReadAllValidationError(t *testing.T) { 165 testFdWithDigestReadAllValidation(t, 2, errChecksumMismatch) 166 } 167 168 func TestFdWithDigestReadAllValidationSuccess(t *testing.T) { 169 testFdWithDigestReadAllValidation(t, 1, nil) 170 } 171 172 func TestFdWithDigestValidateDigest(t *testing.T) { 173 reader := NewFdWithDigestReader(testReaderBufferSize).(*fdWithDigestReader) 174 reader.readerWithDigest.(*readerWithDigest).digest = &mockDigest{digest: 123} 175 require.NoError(t, reader.Validate(123)) 176 require.Equal(t, errChecksumMismatch, reader.Validate(100)) 177 } 178 179 func TestFdWithDigestReaderClose(t *testing.T) { 180 reader, fd, _ := createTestFdWithDigestReader(t) 181 defer func() { 182 fd.Close() 183 os.Remove(fd.Name()) 184 }() 185 186 require.NotNil(t, reader.Fd()) 187 require.NoError(t, reader.Close()) 188 require.Nil(t, reader.Fd()) 189 } 190 191 func TestFdWithDigestReadDigestReadError(t *testing.T) { 192 reader, fd, _ := createTestFdWithDigestContentsReader(t) 193 defer func() { 194 fd.Close() 195 os.Remove(fd.Name()) 196 }() 197 198 reader.Reset(nil) 199 _, err := reader.ReadDigest() 200 require.Error(t, err) 201 } 202 203 func TestFdWithDigestReadDigestTooFewBytes(t *testing.T) { 204 reader, fd, _ := createTestFdWithDigestContentsReader(t) 205 defer func() { 206 fd.Close() 207 os.Remove(fd.Name()) 208 }() 209 210 b := []byte{0x1} 211 fd.Write(b) 212 fd.Seek(-1, 1) 213 214 _, err := reader.ReadDigest() 215 require.Equal(t, errReadFewerThanExpectedBytes, err) 216 } 217 218 func TestFdWithDigestReadDigestSuccess(t *testing.T) { 219 reader, fd, _ := createTestFdWithDigestContentsReader(t) 220 defer func() { 221 fd.Close() 222 os.Remove(fd.Name()) 223 }() 224 225 b := []byte{0xa, 0x0, 0x0, 0x0} 226 fd.Write(b) 227 fd.Seek(0, 0) 228 229 res, err := reader.ReadDigest() 230 require.NoError(t, err) 231 require.Equal(t, uint32(10), res) 232 }