github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/fs/accounting/stats_test.go (about)

     1  package accounting
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/ncw/rclone/fs/fserrors"
    10  	"github.com/pkg/errors"
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  func TestETA(t *testing.T) {
    15  	for _, test := range []struct {
    16  		size, total int64
    17  		rate        float64
    18  		wantETA     time.Duration
    19  		wantOK      bool
    20  		wantString  string
    21  	}{
    22  		// Custom String Cases
    23  		{size: 0, total: 365 * 86400, rate: 1.0, wantETA: 365 * 86400 * time.Second, wantOK: true, wantString: "1y"},
    24  		{size: 0, total: 7 * 86400, rate: 1.0, wantETA: 7 * 86400 * time.Second, wantOK: true, wantString: "1w"},
    25  		{size: 0, total: 1 * 86400, rate: 1.0, wantETA: 1 * 86400 * time.Second, wantOK: true, wantString: "1d"},
    26  		{size: 0, total: 1110 * 86400, rate: 1.0, wantETA: 1110 * 86400 * time.Second, wantOK: true, wantString: "3y2w1d"},
    27  		{size: 0, total: 15 * 86400, rate: 1.0, wantETA: 15 * 86400 * time.Second, wantOK: true, wantString: "2w1d"},
    28  		// Composite Custom String Cases
    29  		{size: 0, total: 1.5 * 86400, rate: 1.0, wantETA: 1.5 * 86400 * time.Second, wantOK: true, wantString: "1d12h"},
    30  		{size: 0, total: 95000, rate: 1.0, wantETA: 95000 * time.Second, wantOK: true, wantString: "1d2h23m20s"},
    31  		// Standard Duration String Cases
    32  		{size: 0, total: 100, rate: 1.0, wantETA: 100 * time.Second, wantOK: true, wantString: "1m40s"},
    33  		{size: 50, total: 100, rate: 1.0, wantETA: 50 * time.Second, wantOK: true, wantString: "50s"},
    34  		{size: 100, total: 100, rate: 1.0, wantETA: 0 * time.Second, wantOK: true, wantString: "0s"},
    35  		// No String Cases
    36  		{size: -1, total: 100, rate: 1.0, wantETA: 0, wantOK: false, wantString: "-"},
    37  		{size: 200, total: 100, rate: 1.0, wantETA: 0, wantOK: false, wantString: "-"},
    38  		{size: 10, total: -1, rate: 1.0, wantETA: 0, wantOK: false, wantString: "-"},
    39  		{size: 10, total: 20, rate: 0.0, wantETA: 0, wantOK: false, wantString: "-"},
    40  		{size: 10, total: 20, rate: -1.0, wantETA: 0, wantOK: false, wantString: "-"},
    41  		{size: 0, total: 0, rate: 1.0, wantETA: 0, wantOK: false, wantString: "-"},
    42  	} {
    43  		t.Run(fmt.Sprintf("size=%d/total=%d/rate=%f", test.size, test.total, test.rate), func(t *testing.T) {
    44  			gotETA, gotOK := eta(test.size, test.total, test.rate)
    45  			assert.Equal(t, test.wantETA, gotETA)
    46  			assert.Equal(t, test.wantOK, gotOK)
    47  			gotString := etaString(test.size, test.total, test.rate)
    48  			assert.Equal(t, test.wantString, gotString)
    49  		})
    50  	}
    51  }
    52  
    53  func TestPercentage(t *testing.T) {
    54  	assert.Equal(t, percent(0, 1000), "0%")
    55  	assert.Equal(t, percent(1, 1000), "0%")
    56  	assert.Equal(t, percent(9, 1000), "1%")
    57  	assert.Equal(t, percent(500, 1000), "50%")
    58  	assert.Equal(t, percent(1000, 1000), "100%")
    59  	assert.Equal(t, percent(1E8, 1E9), "10%")
    60  	assert.Equal(t, percent(1E8, 1E9), "10%")
    61  	assert.Equal(t, percent(0, 0), "-")
    62  	assert.Equal(t, percent(100, -100), "-")
    63  	assert.Equal(t, percent(-100, 100), "-")
    64  	assert.Equal(t, percent(-100, -100), "-")
    65  }
    66  
    67  func TestStatsError(t *testing.T) {
    68  	s := NewStats()
    69  	assert.Equal(t, int64(0), s.GetErrors())
    70  	assert.False(t, s.HadFatalError())
    71  	assert.False(t, s.HadRetryError())
    72  	assert.Equal(t, time.Time{}, s.RetryAfter())
    73  	assert.Equal(t, nil, s.GetLastError())
    74  	assert.False(t, s.Errored())
    75  
    76  	t0 := time.Now()
    77  	t1 := t0.Add(time.Second)
    78  
    79  	s.Error(nil)
    80  	assert.Equal(t, int64(0), s.GetErrors())
    81  	assert.False(t, s.HadFatalError())
    82  	assert.False(t, s.HadRetryError())
    83  	assert.Equal(t, time.Time{}, s.RetryAfter())
    84  	assert.Equal(t, nil, s.GetLastError())
    85  	assert.False(t, s.Errored())
    86  
    87  	s.Error(io.EOF)
    88  	assert.Equal(t, int64(1), s.GetErrors())
    89  	assert.False(t, s.HadFatalError())
    90  	assert.True(t, s.HadRetryError())
    91  	assert.Equal(t, time.Time{}, s.RetryAfter())
    92  	assert.Equal(t, io.EOF, s.GetLastError())
    93  	assert.True(t, s.Errored())
    94  
    95  	e := fserrors.ErrorRetryAfter(t0)
    96  	s.Error(e)
    97  	assert.Equal(t, int64(2), s.GetErrors())
    98  	assert.False(t, s.HadFatalError())
    99  	assert.True(t, s.HadRetryError())
   100  	assert.Equal(t, t0, s.RetryAfter())
   101  	assert.Equal(t, e, s.GetLastError())
   102  
   103  	err := errors.Wrap(fserrors.ErrorRetryAfter(t1), "potato")
   104  	s.Error(err)
   105  	assert.Equal(t, int64(3), s.GetErrors())
   106  	assert.False(t, s.HadFatalError())
   107  	assert.True(t, s.HadRetryError())
   108  	assert.Equal(t, t1, s.RetryAfter())
   109  	assert.Equal(t, t1, fserrors.RetryAfterErrorTime(err))
   110  
   111  	s.Error(fserrors.FatalError(io.EOF))
   112  	assert.Equal(t, int64(4), s.GetErrors())
   113  	assert.True(t, s.HadFatalError())
   114  	assert.True(t, s.HadRetryError())
   115  	assert.Equal(t, t1, s.RetryAfter())
   116  
   117  	s.ResetErrors()
   118  	assert.Equal(t, int64(0), s.GetErrors())
   119  	assert.False(t, s.HadFatalError())
   120  	assert.False(t, s.HadRetryError())
   121  	assert.Equal(t, time.Time{}, s.RetryAfter())
   122  	assert.Equal(t, nil, s.GetLastError())
   123  	assert.False(t, s.Errored())
   124  
   125  	s.Error(fserrors.NoRetryError(io.EOF))
   126  	assert.Equal(t, int64(1), s.GetErrors())
   127  	assert.False(t, s.HadFatalError())
   128  	assert.False(t, s.HadRetryError())
   129  	assert.Equal(t, time.Time{}, s.RetryAfter())
   130  }