github.com/thanos-io/thanos@v0.32.5/pkg/store/io_test.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package store
     5  
     6  import (
     7  	"bytes"
     8  	"io"
     9  	"testing"
    10  
    11  	"github.com/pkg/errors"
    12  
    13  	"github.com/efficientgo/core/testutil"
    14  )
    15  
    16  func TestByteRanges_contiguous(t *testing.T) {
    17  	tests := []struct {
    18  		ranges   byteRanges
    19  		expected bool
    20  	}{
    21  		{
    22  			ranges:   nil,
    23  			expected: true,
    24  		}, {
    25  			ranges:   byteRanges{{offset: 10, length: 5}},
    26  			expected: true,
    27  		}, {
    28  			ranges:   byteRanges{{offset: 10, length: 5}, {offset: 15, length: 3}, {offset: 18, length: 2}},
    29  			expected: true,
    30  		}, {
    31  			ranges:   byteRanges{{offset: 10, length: 3}, {offset: 15, length: 3}, {offset: 18, length: 2}},
    32  			expected: false,
    33  		}, {
    34  			ranges:   byteRanges{{offset: 10, length: 5}, {offset: 15, length: 3}, {offset: 19, length: 2}},
    35  			expected: false,
    36  		},
    37  	}
    38  
    39  	for _, tc := range tests {
    40  		testutil.Equals(t, tc.expected, tc.ranges.areContiguous())
    41  	}
    42  }
    43  
    44  func TestReadByteRanges(t *testing.T) {
    45  	tests := map[string]struct {
    46  		src          []byte
    47  		ranges       byteRanges
    48  		expectedRead []byte
    49  		expectedErr  error
    50  	}{
    51  		"no ranges": {
    52  			src:          []byte(""),
    53  			ranges:       nil,
    54  			expectedRead: nil,
    55  		},
    56  		"single range with offset == 0": {
    57  			src:          []byte("ABCDEFGHILMNOPQRSTUVZ"),
    58  			ranges:       []byteRange{{offset: 0, length: 21}},
    59  			expectedRead: []byte("ABCDEFGHILMNOPQRSTUVZ"),
    60  		},
    61  		"single range with offset > 0": {
    62  			src:          []byte("ABCDEFGHILMNOPQRSTUVZ"),
    63  			ranges:       []byteRange{{offset: 10, length: 11}},
    64  			expectedRead: []byte("MNOPQRSTUVZ"),
    65  		},
    66  		"multiple contiguous ranges with first offset == 0": {
    67  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
    68  			ranges: []byteRange{
    69  				{offset: 0, length: 10},
    70  				{offset: 10, length: 10},
    71  				{offset: 20, length: 1},
    72  			},
    73  			expectedRead: []byte("ABCDEFGHILMNOPQRSTUVZ"),
    74  		},
    75  		"multiple contiguous ranges with first offset > 0": {
    76  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
    77  			ranges: []byteRange{
    78  				{offset: 5, length: 5},
    79  				{offset: 10, length: 10},
    80  				{offset: 20, length: 1},
    81  			},
    82  			expectedRead: []byte("FGHILMNOPQRSTUVZ"),
    83  		},
    84  		"multiple non-contiguous ranges": {
    85  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
    86  			ranges: []byteRange{
    87  				{offset: 0, length: 3},
    88  				{offset: 10, length: 5},
    89  				{offset: 16, length: 1},
    90  				{offset: 20, length: 1},
    91  			},
    92  			expectedRead: []byte("ABCMNOPQSZ"),
    93  		},
    94  		"discard bytes before the first range": {
    95  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
    96  			ranges: []byteRange{
    97  				{offset: 5, length: 16},
    98  			},
    99  			expectedRead: []byte("FGHILMNOPQRSTUVZ"),
   100  		},
   101  		"discard bytes after the last range": {
   102  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
   103  			ranges: []byteRange{
   104  				{offset: 0, length: 16},
   105  			},
   106  			expectedRead: []byte("ABCDEFGHILMNOPQR"),
   107  		},
   108  		"unexpected EOF while discarding bytes": {
   109  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
   110  			ranges: []byteRange{
   111  				{offset: 0, length: 16},
   112  				{offset: 25, length: 5},
   113  			},
   114  			expectedErr: io.ErrUnexpectedEOF,
   115  		},
   116  		"unexpected EOF while reading byte range": {
   117  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
   118  			ranges: []byteRange{
   119  				{offset: 20, length: 10},
   120  				{offset: 40, length: 10},
   121  			},
   122  			expectedErr: io.ErrUnexpectedEOF,
   123  		},
   124  		"unexpected EOF at the beginning of a byte range": {
   125  			src: []byte("ABCDEFGHILMNOPQRSTUVZ"),
   126  			ranges: []byteRange{
   127  				{offset: 0, length: 10},
   128  				{offset: 20, length: 1},
   129  				{offset: 21, length: 10},
   130  			},
   131  			expectedErr: io.ErrUnexpectedEOF,
   132  		},
   133  	}
   134  
   135  	for testName, testData := range tests {
   136  		t.Run(testName, func(t *testing.T) {
   137  			actual := make([]byte, 0, 1024)
   138  			actual, err := readByteRanges(bytes.NewReader(testData.src), actual, testData.ranges)
   139  
   140  			if testData.expectedErr != nil {
   141  				testutil.NotOk(t, err)
   142  				testutil.Equals(t, true, errors.Is(err, testData.expectedErr))
   143  			} else {
   144  				testutil.Ok(t, err)
   145  				testutil.Equals(t, testData.expectedRead, actual)
   146  			}
   147  		})
   148  	}
   149  }