github.com/Files-com/files-sdk-go/v2@v2.1.2/file/retrytransfers_test.go (about)

     1  package file
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	files_sdk "github.com/Files-com/files-sdk-go/v2"
    14  	"github.com/Files-com/files-sdk-go/v2/file/manager"
    15  	"github.com/Files-com/files-sdk-go/v2/file/status"
    16  	"github.com/Files-com/files-sdk-go/v2/ignore"
    17  	"github.com/Files-com/files-sdk-go/v2/lib"
    18  	"github.com/Files-com/files-sdk-go/v2/lib/direction"
    19  	"github.com/Files-com/files-sdk-go/v2/lib/timer"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestRetryTransfers(t *testing.T) {
    24  	assert := assert.New(t)
    25  	t.Run("downloads", func(t *testing.T) {
    26  		t.Run("RetryAll RetryCount 1", func(t *testing.T) {
    27  			buildDownloadTest(func(job *status.Job) {
    28  				events := status.EventsReporter{}
    29  				eventsMutex := sync.Mutex{}
    30  				var retryingEvents []status.Status
    31  				job.RegisterFileEvent(func(file status.File) {
    32  					eventsMutex.Lock()
    33  					defer eventsMutex.Unlock()
    34  					retryingEvents = append(retryingEvents, file.Status)
    35  				}, status.Retrying)
    36  				job.SetEventsReporter(events)
    37  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryAll, RetryCount: 1}, false)
    38  				assert.Equal(true, job.All(status.Complete))
    39  				assert.Equal(3, len(retryingEvents), "sets a retrying status before starting")
    40  			})
    41  		})
    42  
    43  		t.Run("RetryUnfinished RetryCount 1", func(t *testing.T) {
    44  			buildDownloadTest(func(job *status.Job) {
    45  				job.Start(false)
    46  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryUnfinished, RetryCount: 1}, false)
    47  				assert.Equal(false, job.All(status.Complete))
    48  				assert.Equal(2, job.Count(status.Complete))
    49  				assert.Equal(1, job.Count(status.Queued))
    50  				assert.Equal(true, job.Started.Called())
    51  				assert.Equal(false, job.Scanning.Called())
    52  				assert.Equal(false, job.EndScanning.Called())
    53  				assert.Equal(false, job.Finished.Called())
    54  				job.Finish()
    55  			})
    56  		})
    57  
    58  		t.Run("RetryUnfinished RetryCount 1 signalEvents true", func(t *testing.T) {
    59  			buildDownloadTest(func(job *status.Job) {
    60  				job.Start()
    61  				job.Finish() // Finish already called, this happens in the desktop app
    62  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryUnfinished, RetryCount: 1}, true)
    63  				assert.Equal(false, job.All(status.Complete))
    64  				assert.Equal(2, job.Count(status.Complete))
    65  				assert.Equal(1, job.Count(status.Queued))
    66  
    67  				assert.Equal(true, job.Started.Called())
    68  				assert.Equal(true, job.Scanning.Called())
    69  				assert.Equal(true, job.EndScanning.Called())
    70  				assert.Equal(true, job.Finished.Called())
    71  			})
    72  		})
    73  
    74  		t.Run("RetryErroredIfSomeCompleted RetryCount 1", func(t *testing.T) {
    75  			buildDownloadTest(func(job *status.Job) {
    76  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryErroredIfSomeCompleted, RetryCount: 1}, false)
    77  				assert.Equal(false, job.All(status.Complete))
    78  				assert.Equal(2, job.Count(status.Complete))
    79  				assert.Equal(1, job.Count(status.Queued))
    80  			})
    81  		})
    82  
    83  		t.Run("RetryErroredIfSomeCompleted RetryCount 1", func(t *testing.T) {
    84  			buildDownloadTest(func(job *status.Job) {
    85  				job.Statuses[0].(*DownloadStatus).lastByte = time.Time{}
    86  				job.Statuses[1].(*DownloadStatus).lastByte = time.Time{}
    87  				job.Statuses[2].(*DownloadStatus).lastByte = time.Time{}
    88  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryErroredIfSomeCompleted, RetryCount: 1}, false)
    89  				assert.Equal(1, job.Count(status.Complete))
    90  				assert.Equal(1, job.Count(status.Queued))
    91  				assert.Equal(1, job.Count(status.Errored), "is not retried because completed happened before this error not after")
    92  			})
    93  		})
    94  	})
    95  	t.Run("uploads", func(t *testing.T) {
    96  		t.Run("RetryAll RetryCount 1", func(t *testing.T) {
    97  			buildUploadTest(func(job *status.Job, _ *MockUploader) {
    98  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryAll, RetryCount: 1}, false)
    99  				assert.Equal(true, job.All(status.Complete))
   100  			})
   101  		})
   102  
   103  		t.Run("RetryUnfinished RetryCount 1", func(t *testing.T) {
   104  			buildUploadTest(func(job *status.Job, _ *MockUploader) {
   105  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryUnfinished, RetryCount: 1}, false)
   106  				assert.Equal(false, job.All(status.Complete))
   107  				assert.Equal(2, job.Count(status.Complete))
   108  				assert.Equal(1, job.Count(status.Queued))
   109  				assert.Equal(false, job.Running(), "does change the original time")
   110  			})
   111  		})
   112  
   113  		t.Run("RetryUnfinished RetryCount 2", func(t *testing.T) {
   114  			buildUploadTest(func(job *status.Job, uploader *MockUploader) {
   115  				uploader.uploadError = fmt.Errorf("bad things")
   116  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryUnfinished, RetryCount: 2, Backoff: -1}, false)
   117  				assert.Equal(false, job.All(status.Complete))
   118  				assert.Equal(1, job.Count(status.Complete))
   119  				assert.Equal(2, job.Count(status.Errored))
   120  				assert.Equal(false, job.Running(), "does change the original time")
   121  			}, status.Errored, status.Errored, status.Complete)
   122  		})
   123  
   124  		t.Run("RetryUnfinished RetryCount 1", func(t *testing.T) {
   125  			buildUploadTest(func(job *status.Job, _ *MockUploader) {
   126  				startTime := time.Now().AddDate(0, -1, 0)
   127  				endTime := time.Now().AddDate(0, -1, 0)
   128  				job.Timer.Runs = timer.Runs{timer.Run{
   129  					Start:  startTime,
   130  					Finish: endTime,
   131  				}}
   132  				uploadStatusErrored := job.Statuses[0].(*UploadStatus)
   133  				uploadStatusErrored.status = status.Complete
   134  				RetryByPolicy(context.Background(), job, RetryPolicy{Type: RetryUnfinished, RetryCount: 1}, false)
   135  				assert.Equal(false, job.All(status.Complete))
   136  				assert.Equal(2, job.Count(status.Complete))
   137  				assert.Equal(1, job.Count(status.Queued))
   138  				assert.Equal(startTime, job.StartTime(), "does not change the original time")
   139  				assert.Equal(endTime, job.FinishTime(), "does not change the original time")
   140  			})
   141  		})
   142  	})
   143  }
   144  
   145  func buildDownloadTest(test func(*status.Job)) {
   146  	job := (&status.Job{Direction: direction.DownloadType, Manager: manager.Default(), Config: files_sdk.Config{}, Logger: (&files_sdk.Config{}).Logger()}).Init()
   147  	temps := make([]string, 3)
   148  	statuses := []status.Status{status.Errored, status.Complete, status.Queued}
   149  	tmpDir, err := ioutil.TempDir(os.TempDir(), "client_test")
   150  	if err != nil {
   151  		log.Fatal(err)
   152  	}
   153  	for i, s := range statuses {
   154  		tempFile, err := ioutil.TempFile(tmpDir, fmt.Sprintf("%v.txt", i))
   155  		if err != nil {
   156  			panic(err)
   157  		}
   158  		_, err = tempFile.Write([]byte("taco"))
   159  		if err != nil {
   160  			panic(err)
   161  		}
   162  		temps = append(temps, tempFile.Name())
   163  		localFile, err := os.Open(tempFile.Name())
   164  		if err != nil {
   165  			panic(err)
   166  		}
   167  		tempFile.Close()
   168  		job.Add(&DownloadStatus{Mutex: &sync.RWMutex{}, lastByte: time.Now(), localPath: tempFile.Name(), fsFile: localFile, status: s, job: job, file: files_sdk.File{DisplayName: fmt.Sprintf("%v.txt", i)}})
   169  	}
   170  
   171  	test(job)
   172  
   173  	for _, tmp := range temps {
   174  		os.Remove(tmp)
   175  	}
   176  	os.RemoveAll(tmpDir)
   177  }
   178  
   179  func buildUploadTest(test func(*status.Job, *MockUploader), statuses ...status.Status) {
   180  	job := (&status.Job{Direction: direction.UploadType, Manager: manager.Default(), Params: UploaderParams{}, Config: files_sdk.Config{}, Logger: (&files_sdk.Config{}).Logger()}).Init()
   181  	job.Ignore, _ = ignore.New()
   182  	var temps []string
   183  	if len(statuses) == 0 {
   184  		statuses = []status.Status{status.Errored, status.Complete, status.Queued}
   185  	}
   186  	uploader := &MockUploader{}
   187  	tmpDir, err := ioutil.TempDir(os.TempDir(), "retrytransfers")
   188  	if err != nil {
   189  		log.Fatal(err)
   190  	}
   191  	for i, s := range statuses {
   192  		tempFile, err := ioutil.TempFile(tmpDir, fmt.Sprintf("%v.txt", i))
   193  		if err != nil {
   194  			panic(err)
   195  		}
   196  		_, err = tempFile.Write([]byte("taco"))
   197  		if err != nil {
   198  			panic(err)
   199  		}
   200  		temps = append(temps, tempFile.Name())
   201  		tempFile.Close()
   202  		job.Add(&UploadStatus{Mutex: &sync.RWMutex{}, Uploader: uploader, lastByte: time.Now(), localPath: tempFile.Name(), status: s, job: job, file: files_sdk.File{DisplayName: fmt.Sprintf("%v.txt", i), Mtime: lib.Time(time.Now())}})
   203  	}
   204  
   205  	test(job, uploader)
   206  
   207  	for _, tmp := range temps {
   208  		os.Remove(tmp)
   209  	}
   210  	if err := os.RemoveAll(tmpDir); err != nil {
   211  		panic(err)
   212  	}
   213  }