github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/fs/accounting/accounting_test.go (about) 1 package accounting 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "strings" 9 "testing" 10 "unicode/utf8" 11 12 "github.com/ncw/rclone/fs" 13 "github.com/ncw/rclone/fs/asyncreader" 14 "github.com/ncw/rclone/fs/fserrors" 15 "github.com/ncw/rclone/fstest/mockobject" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 // Check it satisfies the interfaces 21 var ( 22 _ io.ReadCloser = &Account{} 23 _ io.Reader = &accountStream{} 24 _ Accounter = &Account{} 25 _ Accounter = &accountStream{} 26 ) 27 28 func TestNewAccountSizeName(t *testing.T) { 29 in := ioutil.NopCloser(bytes.NewBuffer([]byte{1})) 30 acc := NewAccountSizeName(in, 1, "test") 31 assert.Equal(t, in, acc.in) 32 assert.Equal(t, acc, Stats.inProgress.get("test")) 33 err := acc.Close() 34 assert.NoError(t, err) 35 assert.Nil(t, Stats.inProgress.get("test")) 36 } 37 38 func TestNewAccount(t *testing.T) { 39 obj := mockobject.Object("test") 40 in := ioutil.NopCloser(bytes.NewBuffer([]byte{1})) 41 acc := NewAccount(in, obj) 42 assert.Equal(t, in, acc.in) 43 assert.Equal(t, acc, Stats.inProgress.get("test")) 44 err := acc.Close() 45 assert.NoError(t, err) 46 assert.Nil(t, Stats.inProgress.get("test")) 47 } 48 49 func TestAccountWithBuffer(t *testing.T) { 50 in := ioutil.NopCloser(bytes.NewBuffer([]byte{1})) 51 52 acc := NewAccountSizeName(in, -1, "test") 53 acc.WithBuffer() 54 // should have a buffer for an unknown size 55 _, ok := acc.in.(*asyncreader.AsyncReader) 56 require.True(t, ok) 57 assert.NoError(t, acc.Close()) 58 59 acc = NewAccountSizeName(in, 1, "test") 60 acc.WithBuffer() 61 // should not have a buffer for a small size 62 _, ok = acc.in.(*asyncreader.AsyncReader) 63 require.False(t, ok) 64 assert.NoError(t, acc.Close()) 65 } 66 67 func TestAccountGetUpdateReader(t *testing.T) { 68 in := ioutil.NopCloser(bytes.NewBuffer([]byte{1})) 69 acc := NewAccountSizeName(in, 1, "test") 70 71 assert.Equal(t, in, acc.GetReader()) 72 73 in2 := ioutil.NopCloser(bytes.NewBuffer([]byte{1})) 74 acc.UpdateReader(in2) 75 76 assert.Equal(t, in2, acc.GetReader()) 77 78 assert.NoError(t, acc.Close()) 79 } 80 81 func TestAccountRead(t *testing.T) { 82 in := ioutil.NopCloser(bytes.NewBuffer([]byte{1, 2, 3})) 83 acc := NewAccountSizeName(in, 1, "test") 84 85 assert.True(t, acc.start.IsZero()) 86 assert.Equal(t, 0, acc.lpBytes) 87 assert.Equal(t, int64(0), acc.bytes) 88 assert.Equal(t, int64(0), Stats.bytes) 89 90 var buf = make([]byte, 2) 91 n, err := acc.Read(buf) 92 assert.NoError(t, err) 93 assert.Equal(t, 2, n) 94 assert.Equal(t, []byte{1, 2}, buf[:n]) 95 96 assert.False(t, acc.start.IsZero()) 97 assert.Equal(t, 2, acc.lpBytes) 98 assert.Equal(t, int64(2), acc.bytes) 99 assert.Equal(t, int64(2), Stats.bytes) 100 101 n, err = acc.Read(buf) 102 assert.NoError(t, err) 103 assert.Equal(t, 1, n) 104 assert.Equal(t, []byte{3}, buf[:n]) 105 106 n, err = acc.Read(buf) 107 assert.Equal(t, io.EOF, err) 108 assert.Equal(t, 0, n) 109 110 assert.NoError(t, acc.Close()) 111 } 112 113 func TestAccountString(t *testing.T) { 114 in := ioutil.NopCloser(bytes.NewBuffer([]byte{1, 2, 3})) 115 acc := NewAccountSizeName(in, 3, "test") 116 117 // FIXME not an exhaustive test! 118 119 assert.Equal(t, "test: 0% /3, 0/s, -", strings.TrimSpace(acc.String())) 120 121 var buf = make([]byte, 2) 122 n, err := acc.Read(buf) 123 assert.NoError(t, err) 124 assert.Equal(t, 2, n) 125 126 assert.Equal(t, "test: 66% /3, 0/s, -", strings.TrimSpace(acc.String())) 127 128 assert.NoError(t, acc.Close()) 129 } 130 131 // Test the Accounter interface methods on Account and accountStream 132 func TestAccountAccounter(t *testing.T) { 133 in := ioutil.NopCloser(bytes.NewBuffer([]byte{1, 2, 3})) 134 acc := NewAccountSizeName(in, 3, "test") 135 136 assert.True(t, in == acc.OldStream()) 137 138 in2 := ioutil.NopCloser(bytes.NewBuffer([]byte{2, 3, 4})) 139 140 acc.SetStream(in2) 141 assert.True(t, in2 == acc.OldStream()) 142 143 r := acc.WrapStream(in) 144 as, ok := r.(Accounter) 145 require.True(t, ok) 146 assert.True(t, in == as.OldStream()) 147 assert.True(t, in2 == acc.OldStream()) 148 accs, ok := r.(*accountStream) 149 require.True(t, ok) 150 assert.Equal(t, acc, accs.acc) 151 assert.True(t, in == accs.in) 152 153 // Check Read on the accountStream 154 var buf = make([]byte, 2) 155 n, err := r.Read(buf) 156 assert.NoError(t, err) 157 assert.Equal(t, 2, n) 158 assert.Equal(t, []byte{1, 2}, buf[:n]) 159 160 // Test that we can get another accountstream out 161 in3 := ioutil.NopCloser(bytes.NewBuffer([]byte{3, 1, 2})) 162 r2 := as.WrapStream(in3) 163 as2, ok := r2.(Accounter) 164 require.True(t, ok) 165 assert.True(t, in3 == as2.OldStream()) 166 assert.True(t, in2 == acc.OldStream()) 167 accs2, ok := r2.(*accountStream) 168 require.True(t, ok) 169 assert.Equal(t, acc, accs2.acc) 170 assert.True(t, in3 == accs2.in) 171 172 // Test we can set this new accountStream 173 as2.SetStream(in) 174 assert.True(t, in == as2.OldStream()) 175 176 // Test UnWrap on accountStream 177 unwrapped, wrap := UnWrap(r2) 178 assert.True(t, unwrapped == in) 179 r3 := wrap(in2) 180 assert.True(t, in2 == r3.(Accounter).OldStream()) 181 182 // TestUnWrap on a normal io.Reader 183 unwrapped, wrap = UnWrap(in2) 184 assert.True(t, unwrapped == in2) 185 assert.True(t, wrap(in3) == in3) 186 187 } 188 189 func TestAccountMaxTransfer(t *testing.T) { 190 old := fs.Config.MaxTransfer 191 fs.Config.MaxTransfer = 15 192 defer func() { 193 fs.Config.MaxTransfer = old 194 }() 195 Stats.ResetCounters() 196 197 in := ioutil.NopCloser(bytes.NewBuffer(make([]byte, 100))) 198 acc := NewAccountSizeName(in, 1, "test") 199 200 var b = make([]byte, 10) 201 202 n, err := acc.Read(b) 203 assert.Equal(t, 10, n) 204 assert.NoError(t, err) 205 n, err = acc.Read(b) 206 assert.Equal(t, 10, n) 207 assert.NoError(t, err) 208 n, err = acc.Read(b) 209 assert.Equal(t, 0, n) 210 assert.Equal(t, ErrorMaxTransferLimitReached, err) 211 assert.True(t, fserrors.IsFatalError(err)) 212 } 213 214 func TestShortenName(t *testing.T) { 215 for _, test := range []struct { 216 in string 217 size int 218 want string 219 }{ 220 {"", 0, ""}, 221 {"abcde", 10, "abcde"}, 222 {"abcde", 0, "abcde"}, 223 {"abcde", -1, "abcde"}, 224 {"abcde", 5, "abcde"}, 225 {"abcde", 4, "ab…e"}, 226 {"abcde", 3, "a…e"}, 227 {"abcde", 2, "a…"}, 228 {"abcde", 1, "…"}, 229 {"abcdef", 6, "abcdef"}, 230 {"abcdef", 5, "ab…ef"}, 231 {"abcdef", 4, "ab…f"}, 232 {"abcdef", 3, "a…f"}, 233 {"abcdef", 2, "a…"}, 234 {"áßcdèf", 1, "…"}, 235 {"áßcdè", 5, "áßcdè"}, 236 {"áßcdè", 4, "áß…è"}, 237 {"áßcdè", 3, "á…è"}, 238 {"áßcdè", 2, "á…"}, 239 {"áßcdè", 1, "…"}, 240 {"áßcdèł", 6, "áßcdèł"}, 241 {"áßcdèł", 5, "áß…èł"}, 242 {"áßcdèł", 4, "áß…ł"}, 243 {"áßcdèł", 3, "á…ł"}, 244 {"áßcdèł", 2, "á…"}, 245 {"áßcdèł", 1, "…"}, 246 } { 247 t.Run(fmt.Sprintf("in=%q, size=%d", test.in, test.size), func(t *testing.T) { 248 got := shortenName(test.in, test.size) 249 assert.Equal(t, test.want, got) 250 if test.size > 0 { 251 assert.True(t, utf8.RuneCountInString(got) <= test.size, "too big") 252 } 253 }) 254 } 255 }