github.com/qiniu/go-sdk/v7@v7.27.0/storage/resume_uploader_v2_test.go (about)

     1  //go:build integration
     2  // +build integration
     3  
     4  package storage
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"crypto/md5"
    10  	"encoding/hex"
    11  	"fmt"
    12  	"io"
    13  	"math/rand"
    14  	"os"
    15  	"path/filepath"
    16  	"sync/atomic"
    17  	"testing"
    18  	"time"
    19  )
    20  
    21  func TestPutWithoutSizeV2(t *testing.T) {
    22  	var putRet PutRet
    23  	putPolicy := PutPolicy{
    24  		Scope:           testBucket,
    25  		DeleteAfterDays: 7,
    26  	}
    27  	upToken := putPolicy.UploadToken(mac)
    28  
    29  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
    30  	sizes := []int64{
    31  		64,
    32  		1 << blockBits,
    33  		(1 << blockBits) - 1,
    34  		(1 << blockBits) + 1,
    35  		(1 << (blockBits + 4)) + 1,
    36  	}
    37  	partSizes := []int64{0, 1 << 20, 1 << 24}
    38  
    39  	for _, partSize := range partSizes {
    40  		for _, size := range sizes {
    41  			md5Sumer := md5.New()
    42  			rd := io.TeeReader(&io.LimitedReader{R: r, N: size}, md5Sumer)
    43  			testKey := fmt.Sprintf("testRPutFileV2Key_%d", r.Int())
    44  			err := resumeUploaderV2.PutWithoutSize(context.Background(), &putRet, upToken, testKey, rd, &RputV2Extra{
    45  				PartSize: partSize,
    46  				Notify: func(partNumber int64, ret *UploadPartsRet) {
    47  					t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
    48  				},
    49  				NotifyErr: func(partNumber int64, err error) {
    50  					t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
    51  				},
    52  			})
    53  			if err != nil {
    54  				t.Fatalf("PutWithoutSize() error, %s", err)
    55  			}
    56  			md5Value := hex.EncodeToString(md5Sumer.Sum(nil))
    57  			validateMD5(t, testKey, md5Value, size)
    58  			t.Logf("Size: %d, Part: %d, Key: %s, Hash:%s", size, partSize, putRet.Key, putRet.Hash)
    59  		}
    60  	}
    61  }
    62  
    63  func TestPutWithSizeV2(t *testing.T) {
    64  	var putRet PutRet
    65  	putPolicy := PutPolicy{
    66  		Scope:           testBucket,
    67  		DeleteAfterDays: 7,
    68  	}
    69  	upToken := putPolicy.UploadToken(mac)
    70  
    71  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
    72  	sizes := []int64{
    73  		64,
    74  		1 << blockBits,
    75  		(1 << blockBits) - 1,
    76  		(1 << blockBits) + 1,
    77  		(1 << (blockBits + 4)) + 1,
    78  	}
    79  	partSizes := []int64{0, 1 << 20, 1 << 24}
    80  
    81  	hostSelector := 0
    82  	for _, partSize := range partSizes {
    83  		hostSelector += 1
    84  		for _, size := range sizes {
    85  			hostSelector += 1
    86  			upHost := ""
    87  			if hostSelector%3 == 1 {
    88  				upHost = testUpHost
    89  			} else {
    90  				upHost = "https://" + testUpHost
    91  			}
    92  
    93  			data := make([]byte, size)
    94  			if _, err := io.ReadFull(r, data); err != nil {
    95  				t.Error(err)
    96  			}
    97  			testKey := fmt.Sprintf("testRPutFileV2Key_%d", r.Int())
    98  			err := resumeUploaderV2.Put(context.Background(), &putRet, upToken, testKey, bytes.NewReader(data), size, &RputV2Extra{
    99  				PartSize: partSize,
   100  				UpHost:   upHost,
   101  				Notify: func(partNumber int64, ret *UploadPartsRet) {
   102  					t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
   103  				},
   104  				NotifyErr: func(partNumber int64, err error) {
   105  					t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
   106  				},
   107  			})
   108  			if err != nil {
   109  				t.Fatalf("Put() error, %s", err)
   110  			}
   111  			md5ByteArray := md5.Sum(data)
   112  			md5Value := hex.EncodeToString(md5ByteArray[:])
   113  			validateMD5(t, testKey, md5Value, size)
   114  			t.Logf("Size: %d, Part: %d, Key: %s, Hash:%s", size, partSize, putRet.Key, putRet.Hash)
   115  		}
   116  	}
   117  	for _, partSize := range partSizes {
   118  		for _, size := range sizes {
   119  			md5Sumer := md5.New()
   120  			testKey := fmt.Sprintf("testRPutFileV2Key_%d_*", r.Int())
   121  			tmpFile, err := os.CreateTemp("", testKey)
   122  			if err != nil {
   123  				t.Error(err)
   124  			}
   125  			defer os.Remove(tmpFile.Name())
   126  			defer tmpFile.Close()
   127  
   128  			if _, err = io.CopyN(tmpFile, io.TeeReader(r, md5Sumer), size); err != nil {
   129  				t.Error(err)
   130  			} else if err = tmpFile.Close(); err != nil {
   131  				t.Error(err)
   132  			}
   133  			err = resumeUploaderV2.PutFile(context.Background(), &putRet, upToken, testKey, tmpFile.Name(), &RputV2Extra{
   134  				PartSize: partSize,
   135  				Notify: func(partNumber int64, ret *UploadPartsRet) {
   136  					t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
   137  				},
   138  				NotifyErr: func(partNumber int64, err error) {
   139  					t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
   140  				},
   141  			})
   142  			if err != nil {
   143  				t.Fatalf("PutFile() error, %s", err)
   144  			}
   145  			md5ByteArray := md5Sumer.Sum(nil)
   146  			md5Value := hex.EncodeToString(md5ByteArray[:])
   147  			validateMD5(t, testKey, md5Value, size)
   148  			t.Logf("Size: %d, Part: %d, Key: %s, Hash:%s", size, partSize, putRet.Key, putRet.Hash)
   149  		}
   150  	}
   151  }
   152  
   153  func TestPutWithoutKeyV2(t *testing.T) {
   154  	var putRet PutRet
   155  	putPolicy := PutPolicy{
   156  		Scope:           testBucket,
   157  		DeleteAfterDays: 7,
   158  	}
   159  	upToken := putPolicy.UploadToken(mac)
   160  
   161  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
   162  	data := make([]byte, 64)
   163  	if _, err := io.ReadFull(r, data); err != nil {
   164  		t.Error(err)
   165  	}
   166  	err := resumeUploaderV2.PutWithoutKey(context.Background(), &putRet, upToken, bytes.NewReader(data), int64(len(data)), &RputV2Extra{
   167  		Notify: func(partNumber int64, ret *UploadPartsRet) {
   168  			t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
   169  		},
   170  		NotifyErr: func(partNumber int64, err error) {
   171  			t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
   172  		},
   173  	})
   174  	if err != nil {
   175  		t.Fatalf("PutWithoutKey() error, %s", err)
   176  	}
   177  	t.Logf("Key: %s, Hash:%s", putRet.Key, putRet.Hash)
   178  
   179  	tmpFile, err := os.CreateTemp("", "")
   180  	if err != nil {
   181  		t.Error(err)
   182  	}
   183  	if _, err = io.Copy(tmpFile, bytes.NewReader(data)); err != nil {
   184  		t.Error(err)
   185  	} else if err = tmpFile.Close(); err != nil {
   186  		t.Error(err)
   187  	}
   188  	err = resumeUploaderV2.PutFileWithoutKey(context.Background(), &putRet, upToken, tmpFile.Name(), &RputV2Extra{
   189  		Notify: func(partNumber int64, ret *UploadPartsRet) {
   190  			t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
   191  		},
   192  		NotifyErr: func(partNumber int64, err error) {
   193  			t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
   194  		},
   195  	})
   196  	if err != nil {
   197  		t.Fatalf("PutWithoutKey() error, %s", err)
   198  	}
   199  	t.Logf("Key: %s, Hash:%s", putRet.Key, putRet.Hash)
   200  }
   201  
   202  func TestPutWithRecoveryV2(t *testing.T) {
   203  	var putRet PutRet
   204  	putPolicy := PutPolicy{
   205  		Scope:           testBucket,
   206  		DeleteAfterDays: 7,
   207  	}
   208  	upToken := putPolicy.UploadToken(mac)
   209  
   210  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
   211  	testKey := fmt.Sprintf("testRPutFileKey_%d", r.Int())
   212  	dirName, err := os.MkdirTemp("", "")
   213  	if err != nil {
   214  		t.Fatal(err)
   215  	}
   216  	defer os.RemoveAll(dirName)
   217  	recorder, err := NewFileRecorder(dirName)
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  
   222  	t.Logf("recorder path:%s", dirName)
   223  	fileName := filepath.Join(dirName, "originalFile")
   224  	testFile, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   225  	if err != nil {
   226  		t.Fatal(err)
   227  	}
   228  	defer testFile.Close()
   229  
   230  	size := int64(4 * (1 << blockBits))
   231  	io.CopyN(testFile, r, size)
   232  
   233  	for i := 0; i < 4; i++ {
   234  		ctx, cancelFunc := context.WithCancel(context.Background())
   235  		counter := uint32(0)
   236  		err = resumeUploaderV2.PutFile(ctx, &putRet, upToken, testKey, fileName, &RputV2Extra{
   237  			Recorder: recorder,
   238  			Notify: func(partNumber int64, ret *UploadPartsRet) {
   239  				t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
   240  				if atomic.AddUint32(&counter, 1) >= 2 {
   241  					cancelFunc()
   242  				}
   243  			},
   244  			NotifyErr: func(partNumber int64, err error) {
   245  				t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
   246  			},
   247  		})
   248  		if err == nil {
   249  			return
   250  		}
   251  	}
   252  	t.Fatal(err)
   253  }
   254  
   255  func TestPutWithBackupV2(t *testing.T) {
   256  	var putRet PutRet
   257  	putPolicy := PutPolicy{
   258  		Scope:           testBucket,
   259  		DeleteAfterDays: 7,
   260  	}
   261  	upToken := putPolicy.UploadToken(mac)
   262  
   263  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
   264  	sizes := []int64{
   265  		64,
   266  		1 << blockBits,
   267  		(1 << blockBits) - 1,
   268  		(1 << blockBits) + 1,
   269  		(1 << (blockBits + 4)) + 1,
   270  	}
   271  	chunkSizes := []int{0, 1 << 20}
   272  
   273  	region, err := GetRegion(mac.AccessKey, testBucket)
   274  	if err != nil {
   275  		t.Fatal("get region error:", err)
   276  	}
   277  
   278  	customizedHost := []string{"mock.qiniu.com"}
   279  	customizedHost = append(customizedHost, region.SrcUpHosts...)
   280  	region.SrcUpHosts = customizedHost
   281  	cfg := Config{}
   282  	cfg.UseCdnDomains = false
   283  	cfg.Region = region
   284  	uploader := NewResumeUploaderV2(&cfg)
   285  
   286  	hostSelector := 0
   287  	for _, chunkSize := range chunkSizes {
   288  		hostSelector += 1
   289  		for _, size := range sizes {
   290  			hostSelector += 1
   291  			data := make([]byte, size)
   292  			if _, err := io.ReadFull(r, data); err != nil {
   293  				t.Fatal(err)
   294  			}
   295  			testKey := fmt.Sprintf("testRPutFileKey_%d", r.Int())
   296  			err := uploader.Put(context.Background(), &putRet, upToken, testKey, bytes.NewReader(data), size, &RputV2Extra{
   297  				Notify: func(partNumber int64, ret *UploadPartsRet) {
   298  					t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
   299  				},
   300  				NotifyErr: func(partNumber int64, err error) {
   301  					t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
   302  				},
   303  			})
   304  			if err != nil {
   305  				t.Fatalf("Put() error, %s", err)
   306  			}
   307  			md5ByteArray := md5.Sum(data)
   308  			md5Value := hex.EncodeToString(md5ByteArray[:])
   309  			validateMD5(t, testKey, md5Value, size)
   310  			t.Logf("Size: %d, Chunk: %d, Key: %s, Hash:%s", size, chunkSize, putRet.Key, putRet.Hash)
   311  		}
   312  	}
   313  }
   314  
   315  func TestPutWithEmptyKeyV2(t *testing.T) {
   316  	bucketManager.Delete(testBucket, "")
   317  
   318  	var putRet PutRet
   319  	putPolicy := PutPolicy{
   320  		Scope:           testBucket + ":",
   321  		DeleteAfterDays: 7,
   322  	}
   323  	upToken := putPolicy.UploadToken(mac)
   324  
   325  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
   326  	data := make([]byte, 64)
   327  	if _, err := io.ReadFull(r, data); err != nil {
   328  		t.Error(err)
   329  	}
   330  	err := resumeUploaderV2.Put(context.Background(), &putRet, upToken, "", bytes.NewReader(data), int64(len(data)), &RputV2Extra{
   331  		Notify: func(partNumber int64, ret *UploadPartsRet) {
   332  			t.Logf("Notify: partNumber: %d, ret: %#v", partNumber, ret)
   333  		},
   334  		NotifyErr: func(partNumber int64, err error) {
   335  			t.Logf("NotifyErr: partNumber: %d, err: %s", partNumber, err)
   336  		},
   337  	})
   338  	if err != nil {
   339  		t.Fatalf("Put() error, %s", err)
   340  	}
   341  	t.Logf("Key: %s, Hash:%s", putRet.Key, putRet.Hash)
   342  }