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  }