github.com/jotfs/jot@v0.2.0/client_test.go (about)

     1  package jot
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"math/rand"
    10  	"net/http"
    11  	"os"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  func TestNew(t *testing.T) {
    19  	// New
    20  	_, err := New("https://localhost:8000", http.DefaultClient, nil)
    21  	assert.NoError(t, err)
    22  
    23  	// New with options
    24  	client, err := New("http://example.com", http.DefaultClient, &Options{
    25  		Compression: CompressNone,
    26  		CacheDir:    "/var/log",
    27  	})
    28  	assert.NoError(t, err)
    29  	assert.Equal(t, CompressNone, client.mode)
    30  	assert.Equal(t, "/var/log", client.cacheDir)
    31  
    32  	// Error if endpoint string is empty
    33  	client, err = New("", http.DefaultClient, nil)
    34  	assert.Error(t, err)
    35  	assert.Nil(t, client)
    36  }
    37  
    38  func TestUpload(t *testing.T) {
    39  	client := testClient(t)
    40  	defer clearFiles(t, client)
    41  
    42  	// Upload data
    43  	data := randBytes(130*miB, 7456)
    44  	_, err := client.Upload(bytes.NewReader(data), "data.txt")
    45  	assert.NoError(t, err)
    46  
    47  	// Upload empty data
    48  	ctx := context.Background()
    49  	_, err = client.UploadWithContext(ctx, bytes.NewReader(nil), "data2.txt", CompressNone)
    50  	assert.NoError(t, err)
    51  }
    52  
    53  func TestDownload(t *testing.T) {
    54  	client := testClient(t)
    55  	defer clearFiles(t, client)
    56  
    57  	// Upload data (none & zstd compression) and check download matches original data
    58  	data1 := randBytes(10*miB, 2854)
    59  	for _, mode := range []CompressMode{CompressNone, CompressZstd} {
    60  		s1 := uploadTestFile(t, client, data1, "data1.txt", mode)
    61  
    62  		msg := fmt.Sprintf("mode = %d", mode)
    63  		var buf bytes.Buffer
    64  		err := client.Download(s1, &buf)
    65  		assert.NoError(t, err, msg)
    66  		assert.Equal(t, data1, buf.Bytes(), msg)
    67  	}
    68  
    69  	// Download file which doesn't exist -- should get ErrNotFound
    70  	var buf bytes.Buffer
    71  	err := client.Download(FileID{}, &buf)
    72  	assert.Equal(t, ErrNotFound, err)
    73  
    74  }
    75  
    76  func TestList(t *testing.T) {
    77  	client := testClient(t)
    78  	defer clearFiles(t, client)
    79  
    80  	data1 := randBytes(2*kiB, 6332)
    81  	data2 := randBytes(12*miB, 83)
    82  	data3 := randBytes(10*miB, 9832)
    83  	s1 := uploadTestFile(t, client, data1, "data1.txt", CompressNone)
    84  	s2 := uploadTestFile(t, client, data2, "files/data2.txt", CompressZstd)
    85  	s3 := uploadTestFile(t, client, data3, "files/data3.txt", CompressNone)
    86  
    87  	// We don't know the CreatedAt value here so leave it at zero for each
    88  	info1 := FileInfo{Name: "/data1.txt", Size: uint64(len(data1)), FileID: s1}
    89  	info2 := FileInfo{Name: "/files/data2.txt", Size: uint64(len(data2)), FileID: s2}
    90  	info3 := FileInfo{Name: "/files/data3.txt", Size: uint64(len(data3)), FileID: s3}
    91  
    92  	runIt := func(it FileIterator) ([]FileInfo, error) {
    93  		files := make([]FileInfo, 0)
    94  		for {
    95  			file, err := it.Next()
    96  			if err == io.EOF {
    97  				break
    98  			}
    99  			if err != nil {
   100  				return nil, err
   101  			}
   102  			// Zero the CreatedAt field so we can match it with the expected values
   103  			file.CreatedAt = time.Time{}
   104  			files = append(files, file)
   105  		}
   106  		return files, nil
   107  	}
   108  
   109  	// List
   110  	it := client.List("/", nil)
   111  	files, err := runIt(it)
   112  	assert.NoError(t, err)
   113  	assert.Equal(t, []FileInfo{info3, info2, info1}, files)
   114  
   115  	// List ascending
   116  	it = client.List("/", &ListOpts{Ascending: true})
   117  	files, err = runIt(it)
   118  	assert.NoError(t, err)
   119  	assert.Equal(t, []FileInfo{info1, info2, info3}, files)
   120  
   121  	// List filter
   122  	it = client.List("/", &ListOpts{Exclude: "/files/*", Include: "/files/data2.txt"})
   123  	files, err = runIt(it)
   124  	assert.NoError(t, err)
   125  	assert.Equal(t, []FileInfo{info2, info1}, files)
   126  
   127  	// List -- no matches
   128  	it = client.List("/invalid/", nil)
   129  	files, err = runIt(it)
   130  	assert.NoError(t, err)
   131  	assert.Equal(t, []FileInfo{}, files)
   132  
   133  	// Head
   134  	it = client.Head("data1.txt", nil)
   135  	files, err = runIt(it)
   136  	assert.NoError(t, err)
   137  	assert.Equal(t, []FileInfo{info1}, files)
   138  
   139  	// Head -- no matches
   140  	it = client.Head("does-not-exist", nil)
   141  	files, err = runIt(it)
   142  	assert.NoError(t, err)
   143  	assert.Equal(t, []FileInfo{}, files)
   144  }
   145  
   146  func TestCopy(t *testing.T) {
   147  	client := testClient(t)
   148  	defer clearFiles(t, client)
   149  
   150  	data1 := randBytes(13*miB, 5343)
   151  	s1 := uploadTestFile(t, client, data1, "data1.txt", CompressNone)
   152  
   153  	// Copy
   154  	s2, err := client.Copy(s1, "data/data2.txt")
   155  	assert.NoError(t, err)
   156  
   157  	// Should be able to get file
   158  	var buf bytes.Buffer
   159  	err = client.Download(s2, &buf)
   160  	assert.NoError(t, err)
   161  	assert.Equal(t, data1, buf.Bytes())
   162  
   163  	// Copy does not exist
   164  	_, err = client.Copy(FileID{}, "abc")
   165  	assert.Equal(t, ErrNotFound, err)
   166  }
   167  
   168  func TestMergeErrors(t *testing.T) {
   169  	err1 := errors.New("1")
   170  	err2 := errors.New("2")
   171  
   172  	tests := []struct {
   173  		e      error
   174  		minor  error
   175  		output error
   176  	}{
   177  		{err1, nil, err1},
   178  		{nil, err2, err2},
   179  		{nil, nil, nil},
   180  	}
   181  
   182  	for i, test := range tests {
   183  		assert.Equal(t, test.output, mergeErrors(test.e, test.minor), i)
   184  	}
   185  
   186  	// Check wrapping
   187  	err := mergeErrors(err1, err2)
   188  	assert.Equal(t, err1, errors.Unwrap(err))
   189  }
   190  
   191  func uploadTestFile(t *testing.T, client *Client, data []byte, name string, mode CompressMode) FileID {
   192  	ctx := context.Background()
   193  	s, err := client.UploadWithContext(ctx, bytes.NewReader(data), name, mode)
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  	return s
   198  }
   199  
   200  func clearFiles(t *testing.T, client *Client) {
   201  	it := client.List("/", nil)
   202  	for {
   203  		file, err := it.Next()
   204  		if err == io.EOF {
   205  			break
   206  		}
   207  		if err != nil {
   208  			t.Fatal(err)
   209  		}
   210  		if err = client.Delete(file.FileID); err != nil {
   211  			t.Fatal(err)
   212  		}
   213  	}
   214  }
   215  
   216  func testClient(t *testing.T) *Client {
   217  	client, err := New("http://localhost:6777", http.DefaultClient, nil)
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  	return client
   222  }
   223  
   224  func randBytes(n int, seed int64) []byte {
   225  	b := make([]byte, n)
   226  	rand.Seed(seed)
   227  	rand.Read(b)
   228  	return b
   229  }
   230  
   231  func BenchmarkUpload(b *testing.B) {
   232  	client, err := New("http://localhost:6777", http.DefaultClient, nil)
   233  	if err != nil {
   234  		b.Fatal(err)
   235  	}
   236  
   237  	ctx := context.Background()
   238  	f, err := os.Open("random.txt")
   239  	if err != nil {
   240  		b.Fatal(err)
   241  	}
   242  	_, err = client.UploadWithContext(ctx, f, "random.txt", CompressNone)
   243  	if err != nil {
   244  		b.Fatal(err)
   245  	}
   246  }