github.com/uber/kraken@v0.1.4/lib/torrent/scheduler/dispatch/piecerequest/manager_test.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package piecerequest 15 16 import ( 17 "testing" 18 "time" 19 20 "github.com/andres-erbsen/clock" 21 "github.com/stretchr/testify/require" 22 23 "github.com/uber/kraken/core" 24 "github.com/uber/kraken/utils/bitsetutil" 25 "github.com/uber/kraken/utils/syncutil" 26 ) 27 28 func newManager( 29 clk clock.Clock, 30 timeout time.Duration, 31 policy string, 32 pipelineLimit int) *Manager { 33 34 m, err := NewManager(clk, timeout, policy, pipelineLimit) 35 if err != nil { 36 panic(err) 37 } 38 return m 39 } 40 41 func countsFromInts(priorities ...int) syncutil.Counters { 42 c := syncutil.NewCounters(len(priorities)) 43 for i, p := range priorities { 44 c.Set(i, p) 45 } 46 47 return c 48 } 49 50 func TestManagerPipelineLimit(t *testing.T) { 51 require := require.New(t) 52 53 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 3) 54 55 peerID := core.PeerIDFixture() 56 57 pieces, err := m.ReservePieces(peerID, bitsetutil.FromBools(true, true, true, true), 58 countsFromInts(0, 0, 0, 0), false) 59 require.NoError(err) 60 require.Len(pieces, 3) 61 62 require.Len(m.PendingPieces(peerID), 3) 63 } 64 65 func TestManagerReserveExpiredRequest(t *testing.T) { 66 require := require.New(t) 67 68 clk := clock.NewMock() 69 timeout := 5 * time.Second 70 71 m := newManager(clk, timeout, DefaultPolicy, 1) 72 73 peerID := core.PeerIDFixture() 74 75 pieces, err := m.ReservePieces(peerID, bitsetutil.FromBools(true), 76 countsFromInts(0), false) 77 require.NoError(err) 78 require.Equal([]int{0}, pieces) 79 80 // Further reservations fail. 81 pieces, err = m.ReservePieces(peerID, bitsetutil.FromBools(true), 82 countsFromInts(0), false) 83 require.NoError(err) 84 require.Empty(pieces) 85 86 pieces, err = m.ReservePieces(core.PeerIDFixture(), bitsetutil.FromBools(true), 87 countsFromInts(0), false) 88 require.NoError(err) 89 require.Empty(pieces) 90 91 clk.Add(timeout + 1) 92 93 pieces, err = m.ReservePieces(peerID, bitsetutil.FromBools(true), 94 countsFromInts(0), false) 95 require.NoError(err) 96 require.Equal([]int{0}, pieces) 97 } 98 99 func TestManagerReserveUnsentRequest(t *testing.T) { 100 require := require.New(t) 101 102 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 1) 103 104 peerID := core.PeerIDFixture() 105 106 pieces, err := m.ReservePieces(peerID, bitsetutil.FromBools(true), 107 countsFromInts(0), false) 108 require.NoError(err) 109 require.Equal([]int{0}, pieces) 110 111 // Further reservations fail. 112 pieces, err = m.ReservePieces(peerID, bitsetutil.FromBools(true), 113 countsFromInts(0), false) 114 require.NoError(err) 115 require.Empty(pieces) 116 117 pieces, err = m.ReservePieces(core.PeerIDFixture(), bitsetutil.FromBools(true), 118 countsFromInts(0), false) 119 require.NoError(err) 120 require.Empty(pieces) 121 122 m.MarkUnsent(peerID, 0) 123 124 pieces, err = m.ReservePieces(peerID, bitsetutil.FromBools(true), 125 countsFromInts(0), false) 126 require.NoError(err) 127 require.Equal([]int{0}, pieces) 128 } 129 130 func TestManagerReserveInvalidRequest(t *testing.T) { 131 require := require.New(t) 132 133 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 1) 134 135 peerID := core.PeerIDFixture() 136 137 pieces, err := m.ReservePieces(peerID, bitsetutil.FromBools(true), 138 countsFromInts(0), false) 139 require.NoError(err) 140 require.Equal([]int{0}, pieces) 141 142 // Further reservations fail. 143 pieces, err = m.ReservePieces(peerID, bitsetutil.FromBools(true), 144 countsFromInts(0), false) 145 require.NoError(err) 146 require.Empty(pieces) 147 148 pieces, err = m.ReservePieces(core.PeerIDFixture(), bitsetutil.FromBools(true), 149 countsFromInts(0), false) 150 require.NoError(err) 151 require.Empty(pieces) 152 153 m.MarkInvalid(peerID, 0) 154 155 pieces, err = m.ReservePieces(peerID, bitsetutil.FromBools(true), 156 countsFromInts(0), false) 157 require.NoError(err) 158 require.Equal([]int{0}, pieces) 159 } 160 161 func TestManagerGetFailedRequests(t *testing.T) { 162 require := require.New(t) 163 164 clk := clock.NewMock() 165 timeout := 5 * time.Second 166 167 m := newManager(clk, timeout, RarestFirstPolicy, 1) 168 169 p0 := core.PeerIDFixture() 170 p1 := core.PeerIDFixture() 171 p2 := core.PeerIDFixture() 172 173 pieces, err := m.ReservePieces(p0, bitsetutil.FromBools(true, true, true), 174 countsFromInts(0, 1, 2), false) 175 require.NoError(err) 176 require.Equal([]int{0}, pieces) 177 178 pieces, err = m.ReservePieces(p1, bitsetutil.FromBools(false, true, false), 179 countsFromInts(0, 1, 2), false) 180 require.NoError(err) 181 require.Equal([]int{1}, pieces) 182 183 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(false, false, true), 184 countsFromInts(0, 1, 2), false) 185 require.NoError(err) 186 require.Equal([]int{2}, pieces) 187 188 m.MarkUnsent(p0, 0) 189 m.MarkInvalid(p1, 1) 190 clk.Add(timeout + 1) // Expires p2's request. 191 192 p3 := core.PeerIDFixture() 193 pieces, err = m.ReservePieces(p3, bitsetutil.FromBools(false, false, false, true), 194 countsFromInts(0, 0, 0, 0), false) 195 require.NoError(err) 196 require.Equal([]int{3}, pieces) 197 198 failed := m.GetFailedRequests() 199 200 require.Len(failed, 3) 201 require.Contains(failed, Request{Piece: 0, PeerID: p0, Status: StatusUnsent}) 202 require.Contains(failed, Request{Piece: 1, PeerID: p1, Status: StatusInvalid}) 203 require.Contains(failed, Request{Piece: 2, PeerID: p2, Status: StatusExpired}) 204 } 205 206 func TestManagerClear(t *testing.T) { 207 require := require.New(t) 208 209 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 1) 210 211 peerID := core.PeerIDFixture() 212 213 pieces, err := m.ReservePieces(peerID, bitsetutil.FromBools(true), 214 countsFromInts(0), false) 215 require.NoError(err) 216 require.Equal([]int{0}, pieces) 217 218 require.Len(m.PendingPieces(peerID), 1) 219 220 m.Clear(0) 221 222 require.Empty(m.PendingPieces(peerID)) 223 } 224 225 func TestManagerClearPeer(t *testing.T) { 226 require := require.New(t) 227 228 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 1) 229 230 p1 := core.PeerIDFixture() 231 p2 := core.PeerIDFixture() 232 233 pieces, err := m.ReservePieces(p1, bitsetutil.FromBools(true), 234 countsFromInts(0), false) 235 require.NoError(err) 236 require.Equal([]int{0}, pieces) 237 238 pieces, err = m.ReservePieces(p1, bitsetutil.FromBools(true, true), 239 countsFromInts(0, 1), false) 240 require.NoError(err) 241 require.Empty(pieces) 242 243 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true, true), 244 countsFromInts(0, 1), false) 245 require.NoError(err) 246 require.Equal([]int{1}, pieces) 247 248 m.ClearPeer(p1) 249 250 require.Empty(m.PendingPieces(p1)) 251 require.Equal([]int{1}, m.PendingPieces(p2)) 252 } 253 254 func TestManagerReservePiecesAllowDuplicate(t *testing.T) { 255 require := require.New(t) 256 257 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 2) 258 259 p1 := core.PeerIDFixture() 260 p2 := core.PeerIDFixture() 261 262 pieces, err := m.ReservePieces(p1, bitsetutil.FromBools(true), 263 countsFromInts(0), true) 264 require.NoError(err) 265 require.Equal([]int{0}, pieces) 266 267 // Shouldn't allow duplicates on the same peer. 268 pieces, err = m.ReservePieces(p1, bitsetutil.FromBools(true), 269 countsFromInts(0), true) 270 require.NoError(err) 271 require.Empty(pieces) 272 273 // Should allow duplicates for different peers. 274 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true), 275 countsFromInts(0), true) 276 require.NoError(err) 277 require.Equal([]int{0}, pieces) 278 } 279 280 func TestManagerClearWhenAllowedDuplicates(t *testing.T) { 281 require := require.New(t) 282 283 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 2) 284 285 p1 := core.PeerIDFixture() 286 p2 := core.PeerIDFixture() 287 288 pieces, err := m.ReservePieces(p1, bitsetutil.FromBools(true, true), 289 countsFromInts(0, 0), true) 290 require.NoError(err) 291 require.Equal([]int{0, 1}, pieces) 292 293 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true, true), 294 countsFromInts(0, 0), true) 295 require.NoError(err) 296 require.Equal([]int{0, 1}, pieces) 297 298 m.Clear(0) 299 300 require.Equal([]int{1}, m.PendingPieces(p1)) 301 require.Equal([]int{1}, m.PendingPieces(p2)) 302 } 303 304 func TestManagerClearPeerWhenAllowedDuplicates(t *testing.T) { 305 require := require.New(t) 306 307 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 2) 308 309 p1 := core.PeerIDFixture() 310 p2 := core.PeerIDFixture() 311 312 pieces, err := m.ReservePieces(p1, bitsetutil.FromBools(true, true), 313 countsFromInts(0, 0), true) 314 require.NoError(err) 315 require.Equal([]int{0, 1}, pieces) 316 317 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true, true), 318 countsFromInts(0, 0), true) 319 require.NoError(err) 320 require.Equal([]int{0, 1}, pieces) 321 322 m.ClearPeer(p1) 323 324 require.Empty(m.PendingPieces(p1)) 325 require.Equal([]int{0, 1}, m.PendingPieces(p2)) 326 } 327 328 func TestManagerMarkStatusWhenAllowedDuplicates(t *testing.T) { 329 tests := []struct { 330 desc string 331 mark func(*Manager, core.PeerID, int) 332 }{ 333 { 334 "mark unsent", 335 func(m *Manager, p core.PeerID, i int) { m.MarkUnsent(p, i) }, 336 }, { 337 "mark invalid", 338 func(m *Manager, p core.PeerID, i int) { m.MarkInvalid(p, i) }, 339 }, 340 } 341 for _, test := range tests { 342 t.Run(test.desc, func(t *testing.T) { 343 require := require.New(t) 344 345 m := newManager(clock.NewMock(), 5*time.Second, DefaultPolicy, 2) 346 347 p1 := core.PeerIDFixture() 348 p2 := core.PeerIDFixture() 349 350 pieces, err := m.ReservePieces(p1, bitsetutil.FromBools(true, true), 351 countsFromInts(0, 0), true) 352 require.NoError(err) 353 require.Equal([]int{0, 1}, pieces) 354 355 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true, true), 356 countsFromInts(0, 0), true) 357 require.NoError(err) 358 require.Equal([]int{0, 1}, pieces) 359 360 test.mark(m, p1, 0) 361 362 require.Equal([]int{1}, m.PendingPieces(p1)) 363 require.Equal([]int{0, 1}, m.PendingPieces(p2)) 364 }) 365 } 366 } 367 368 func TestRarestFirstPolicy(t *testing.T) { 369 require := require.New(t) 370 371 m := newManager(clock.NewMock(), 5*time.Second, RarestFirstPolicy, 2) 372 373 p1 := core.PeerIDFixture() 374 p2 := core.PeerIDFixture() 375 p3 := core.PeerIDFixture() 376 377 pieces, err := m.ReservePieces(p1, bitsetutil.FromBools(true, true, false, true), 378 countsFromInts(2, 3, 1, 0), false) 379 require.NoError(err) 380 require.Equal([]int{3, 0}, pieces) 381 382 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true, true, false, true), 383 countsFromInts(2, 3, 1, 0), false) 384 require.NoError(err) 385 require.Equal([]int{1}, pieces) 386 387 pieces, err = m.ReservePieces(p3, bitsetutil.FromBools(true, true, false, true), 388 countsFromInts(2, 3, 1, 0), false) 389 require.NoError(err) 390 require.Empty(pieces) 391 392 pieces, err = m.ReservePieces(p1, bitsetutil.FromBools(true, true, false, true), 393 countsFromInts(2, 3, 1, 0), false) 394 require.NoError(err) 395 require.Empty(pieces) 396 397 m.MarkUnsent(p1, 3) 398 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true, true, false, true), 399 countsFromInts(2, 3, 1, 0), false) 400 require.NoError(err) 401 require.Equal([]int{3}, pieces) 402 403 m.MarkUnsent(p1, 0) 404 pieces, err = m.ReservePieces(p2, bitsetutil.FromBools(true, true, false, true), 405 countsFromInts(2, 3, 1, 0), false) 406 require.NoError(err) 407 require.Empty(pieces) 408 }