github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/fs/chunkedreader/chunkedreader_test.go (about)

     1  package chunkedreader
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"math/rand"
     8  	"testing"
     9  
    10  	"github.com/rclone/rclone/fstest/mockobject"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestChunkedReader(t *testing.T) {
    16  	content := makeContent(t, 1024)
    17  
    18  	for _, mode := range mockobject.SeekModes {
    19  		t.Run(mode.String(), testRead(content, mode))
    20  	}
    21  }
    22  
    23  func testRead(content []byte, mode mockobject.SeekMode) func(*testing.T) {
    24  	return func(t *testing.T) {
    25  		chunkSizes := []int64{-1, 0, 1, 15, 16, 17, 1023, 1024, 1025, 2000}
    26  		offsets := []int64{0, 1, 2, 3, 4, 5, 7, 8, 9, 15, 16, 17, 31, 32, 33,
    27  			63, 64, 65, 511, 512, 513, 1023, 1024, 1025}
    28  		limits := []int64{-1, 0, 1, 31, 32, 33, 1023, 1024, 1025}
    29  		cl := int64(len(content))
    30  		bl := 32
    31  		buf := make([]byte, bl)
    32  
    33  		o := mockobject.New("test.bin").WithContent(content, mode)
    34  		for ics, cs := range chunkSizes {
    35  			for icsMax, csMax := range chunkSizes {
    36  				// skip tests where chunkSize is much bigger than maxChunkSize
    37  				if ics > icsMax+1 {
    38  					continue
    39  				}
    40  
    41  				t.Run(fmt.Sprintf("Chunksize_%d_%d", cs, csMax), func(t *testing.T) {
    42  					cr := New(context.Background(), o, cs, csMax)
    43  
    44  					for _, offset := range offsets {
    45  						for _, limit := range limits {
    46  							what := fmt.Sprintf("offset %d, limit %d", offset, limit)
    47  
    48  							p, err := cr.RangeSeek(context.Background(), offset, io.SeekStart, limit)
    49  							if offset >= cl {
    50  								require.Error(t, err, what)
    51  								return
    52  							}
    53  							require.NoError(t, err, what)
    54  							require.Equal(t, offset, p, what)
    55  
    56  							n, err := cr.Read(buf)
    57  							end := offset + int64(bl)
    58  							if end > cl {
    59  								end = cl
    60  							}
    61  							l := int(end - offset)
    62  							if l < bl {
    63  								require.Equal(t, io.EOF, err, what)
    64  							} else {
    65  								require.NoError(t, err, what)
    66  							}
    67  							require.Equal(t, l, n, what)
    68  							require.Equal(t, content[offset:end], buf[:n], what)
    69  						}
    70  					}
    71  				})
    72  			}
    73  		}
    74  	}
    75  }
    76  
    77  func TestErrorAfterClose(t *testing.T) {
    78  	content := makeContent(t, 1024)
    79  	o := mockobject.New("test.bin").WithContent(content, mockobject.SeekModeNone)
    80  
    81  	// Close
    82  	cr := New(context.Background(), o, 0, 0)
    83  	require.NoError(t, cr.Close())
    84  	require.Error(t, cr.Close())
    85  
    86  	// Read
    87  	cr = New(context.Background(), o, 0, 0)
    88  	require.NoError(t, cr.Close())
    89  	var buf [1]byte
    90  	_, err := cr.Read(buf[:])
    91  	require.Error(t, err)
    92  
    93  	// Seek
    94  	cr = New(context.Background(), o, 0, 0)
    95  	require.NoError(t, cr.Close())
    96  	_, err = cr.Seek(1, io.SeekCurrent)
    97  	require.Error(t, err)
    98  
    99  	// RangeSeek
   100  	cr = New(context.Background(), o, 0, 0)
   101  	require.NoError(t, cr.Close())
   102  	_, err = cr.RangeSeek(context.Background(), 1, io.SeekCurrent, 0)
   103  	require.Error(t, err)
   104  }
   105  
   106  func makeContent(t *testing.T, size int) []byte {
   107  	content := make([]byte, size)
   108  	r := rand.New(rand.NewSource(42))
   109  	_, err := io.ReadFull(r, content)
   110  	assert.NoError(t, err)
   111  	return content
   112  }