github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/interval/range_group_test.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package interval 12 13 import ( 14 "bytes" 15 "crypto/rand" 16 "reflect" 17 "testing" 18 19 _ "github.com/cockroachdb/cockroach/pkg/util/log" // for flags 20 "github.com/cockroachdb/errors" 21 ) 22 23 func forEachRangeGroupImpl(t *testing.T, fn func(t *testing.T, rg RangeGroup)) { 24 for _, constr := range []func() RangeGroup{ 25 NewRangeList, 26 NewRangeTree, 27 } { 28 rg := constr() 29 name := reflect.TypeOf(rg).Elem().Name() 30 t.Run(name, func(t *testing.T) { 31 fn(t, rg) 32 }) 33 } 34 } 35 36 func TestRangeGroupAddSingleRangeAndClear(t *testing.T) { 37 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 38 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added { 39 t.Errorf("added new range to range group, wanted true added flag; got false") 40 } 41 42 if l := rg.Len(); l != 1 { 43 t.Errorf("added 1 range to range group, wanted len = 1; got len = %d", l) 44 } 45 46 rg.Clear() 47 if l := rg.Len(); l != 0 { 48 t.Errorf("cleared range group, wanted len = 0; got len = %d", l) 49 } 50 }) 51 } 52 53 func TestRangeGroupAddTwoRangesBefore(t *testing.T) { 54 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 55 if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added { 56 t.Errorf("added new range to range group, wanted true added flag; got false") 57 } 58 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added { 59 t.Errorf("added new range to range group, wanted true added flag; got false") 60 } 61 62 if l := rg.Len(); l != 2 { 63 t.Errorf("added 2 disjoint ranges to range group, wanted len = 2; got len = %d", l) 64 } 65 }) 66 } 67 68 func TestRangeGroupAddTwoRangesAfter(t *testing.T) { 69 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 70 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added { 71 t.Errorf("added new range to range group, wanted true added flag; got false") 72 } 73 if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added { 74 t.Errorf("added new range to range group, wanted true added flag; got false") 75 } 76 77 if l := rg.Len(); l != 2 { 78 t.Errorf("added 2 disjoint ranges to range group, wanted len = 2; got len = %d", l) 79 } 80 }) 81 } 82 83 func TestRangeGroupAddTwoRangesMergeForward(t *testing.T) { 84 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 85 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added { 86 t.Errorf("added new range to range group, wanted true added flag; got false") 87 } 88 if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added { 89 t.Errorf("added new range to range group, wanted true added flag; got false") 90 } 91 92 if l := rg.Len(); l != 1 { 93 t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l) 94 } 95 }) 96 } 97 98 func TestRangeGroupAddTwoRangesMergeBackwards(t *testing.T) { 99 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 100 if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added { 101 t.Errorf("added new range to range group, wanted true added flag; got false") 102 } 103 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added { 104 t.Errorf("added new range to range group, wanted true added flag; got false") 105 } 106 107 if l := rg.Len(); l != 1 { 108 t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l) 109 } 110 }) 111 } 112 113 func TestRangeGroupAddTwoRangesWithin(t *testing.T) { 114 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 115 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x04}}); !added { 116 t.Errorf("added new range to range group, wanted true added flag; got false") 117 } 118 if added := rg.Add(Range{Start: []byte{0x02}, End: []byte{0x03}}); added { 119 t.Errorf("added fully contained range to range group, wanted false added flag; got true") 120 } 121 122 if l := rg.Len(); l != 1 { 123 t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l) 124 } 125 }) 126 } 127 128 func TestRangeGroupAddTwoRangesSurround(t *testing.T) { 129 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 130 if added := rg.Add(Range{Start: []byte{0x02}, End: []byte{0x03}}); !added { 131 t.Errorf("added new range to range group, wanted true added flag; got false") 132 } 133 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x04}}); !added { 134 t.Errorf("added new range to range group, wanted true added flag; got false") 135 } 136 137 if l := rg.Len(); l != 1 { 138 t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l) 139 } 140 }) 141 } 142 143 func TestRangeGroupAddThreeRangesMergeInOrder(t *testing.T) { 144 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 145 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added { 146 t.Errorf("added new range to range group, wanted true added flag; got false") 147 } 148 if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added { 149 t.Errorf("added new range to range group, wanted true added flag; got false") 150 } 151 if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added { 152 t.Errorf("added new range to range group, wanted true added flag; got false") 153 } 154 155 if l := rg.Len(); l != 1 { 156 t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l) 157 } 158 }) 159 } 160 161 func TestRangeGroupAddThreeRangesMergeOutOfOrder(t *testing.T) { 162 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 163 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added { 164 t.Errorf("added new range to range group, wanted true added flag; got false") 165 } 166 if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added { 167 t.Errorf("added new range to range group, wanted true added flag; got false") 168 } 169 if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added { 170 t.Errorf("added new range to range group, wanted true added flag; got false") 171 } 172 173 if l := rg.Len(); l != 1 { 174 t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l) 175 } 176 }) 177 } 178 179 func TestRangeGroupAddThreeRangesMergeReverseOrder(t *testing.T) { 180 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 181 if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added { 182 t.Errorf("added new range to range group, wanted true added flag; got false") 183 } 184 if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added { 185 t.Errorf("added new range to range group, wanted true added flag; got false") 186 } 187 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added { 188 t.Errorf("added new range to range group, wanted true added flag; got false") 189 } 190 191 if l := rg.Len(); l != 1 { 192 t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l) 193 } 194 }) 195 } 196 197 func TestRangeGroupAddThreeRangesSuperset(t *testing.T) { 198 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 199 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added { 200 t.Errorf("added new range to range group, wanted true added flag; got false") 201 } 202 if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added { 203 t.Errorf("added new range to range group, wanted true added flag; got false") 204 } 205 if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x06}}); !added { 206 t.Errorf("added new range to range group, wanted true added flag; got false") 207 } 208 209 if l := rg.Len(); l != 1 { 210 t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l) 211 } 212 }) 213 } 214 215 func TestRangeGroupSubRanges(t *testing.T) { 216 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 217 oneRange := []Range{{Start: []byte{0x01}, End: []byte{0x05}}} 218 twoRanges := []Range{ 219 {Start: []byte{0x01}, End: []byte{0x05}}, 220 {Start: []byte{0x07}, End: []byte{0x0f}}, 221 } 222 223 tests := []struct { 224 add []Range 225 sub Range 226 rem bool 227 res []Range 228 }{ 229 { 230 add: []Range{}, 231 sub: Range{Start: []byte{0x10}, End: []byte{0x11}}, 232 rem: false, 233 res: []Range{}, 234 }, 235 { 236 add: oneRange, 237 sub: Range{Start: []byte{0x10}, End: []byte{0x11}}, 238 rem: false, 239 res: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 240 }, 241 { 242 add: oneRange, 243 sub: Range{Start: []byte{0x01}, End: []byte{0x05}}, 244 rem: true, 245 res: []Range{}, 246 }, 247 { 248 add: oneRange, 249 sub: Range{Start: []byte{0x00}, End: []byte{0x06}}, 250 rem: true, 251 res: []Range{}, 252 }, 253 { 254 add: oneRange, 255 sub: Range{Start: []byte{0x04}, End: []byte{0x06}}, 256 rem: true, 257 res: []Range{{Start: []byte{0x01}, End: []byte{0x04}}}, 258 }, 259 { 260 add: oneRange, 261 sub: Range{Start: []byte{0x05}, End: []byte{0x06}}, 262 rem: false, 263 res: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 264 }, 265 { 266 add: oneRange, 267 sub: Range{Start: []byte{0x01}, End: []byte{0x03}}, 268 rem: true, 269 res: []Range{{Start: []byte{0x03}, End: []byte{0x05}}}, 270 }, 271 { 272 add: oneRange, 273 sub: Range{Start: []byte{0x02}, End: []byte{0x04}}, 274 rem: true, 275 res: []Range{ 276 {Start: []byte{0x01}, End: []byte{0x02}}, 277 {Start: []byte{0x04}, End: []byte{0x05}}, 278 }, 279 }, 280 { 281 add: twoRanges, 282 sub: Range{Start: []byte{0x10}, End: []byte{0x11}}, 283 rem: false, 284 res: []Range{ 285 {Start: []byte{0x01}, End: []byte{0x05}}, 286 {Start: []byte{0x07}, End: []byte{0x0f}}, 287 }, 288 }, 289 { 290 add: twoRanges, 291 sub: Range{Start: []byte{0x01}, End: []byte{0x04}}, 292 rem: true, 293 res: []Range{ 294 {Start: []byte{0x04}, End: []byte{0x05}}, 295 {Start: []byte{0x07}, End: []byte{0x0f}}, 296 }, 297 }, 298 { 299 add: twoRanges, 300 sub: Range{Start: []byte{0x01}, End: []byte{0x05}}, 301 rem: true, 302 res: []Range{{Start: []byte{0x07}, End: []byte{0x0f}}}, 303 }, 304 { 305 add: twoRanges, 306 sub: Range{Start: []byte{0x03}, End: []byte{0x09}}, 307 rem: true, 308 res: []Range{ 309 {Start: []byte{0x01}, End: []byte{0x03}}, 310 {Start: []byte{0x09}, End: []byte{0x0f}}, 311 }, 312 }, 313 { 314 add: twoRanges, 315 sub: Range{Start: []byte{0x03}, End: []byte{0xff}}, 316 rem: true, 317 res: []Range{ 318 {Start: []byte{0x01}, End: []byte{0x03}}, 319 }, 320 }, 321 { 322 add: twoRanges, 323 sub: Range{Start: []byte{0x00}, End: []byte{0x09}}, 324 rem: true, 325 res: []Range{ 326 {Start: []byte{0x09}, End: []byte{0x0f}}, 327 }, 328 }, 329 } 330 331 for _, test := range tests { 332 rg.Clear() 333 334 for _, r := range test.add { 335 if added := rg.Add(r); !added { 336 t.Errorf("added new range %v to empty range group, wanted true added flag; got false", r) 337 } 338 } 339 str := rg.String() 340 341 if rem := rg.Sub(test.sub); rem != test.rem { 342 t.Errorf("subtracted %v from range group %s, wanted %t removed flag; got %t", test.sub, str, test.rem, rem) 343 } 344 345 if l, el := rg.Len(), len(test.res); l != el { 346 t.Errorf("subtracted %v from range group %s, wanted %b remaining ranges; got %b", test.sub, str, el, l) 347 } else { 348 ranges := make([]Range, 0, l) 349 if err := rg.ForEach(func(r Range) error { 350 ranges = append(ranges, r) 351 return nil 352 }); err != nil { 353 t.Fatal(err) 354 } 355 356 if !reflect.DeepEqual(ranges, test.res) { 357 t.Errorf("subtracted %v from range group %s, wanted the remaining ranges %v; got %v", test.sub, str, test.res, ranges) 358 } 359 } 360 } 361 }) 362 } 363 364 func TestRangeGroupOverlapsRange(t *testing.T) { 365 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 366 for _, r := range []Range{ 367 {Start: []byte{0x01}, End: []byte{0x05}}, 368 {Start: []byte{0x07}, End: []byte{0x0f}}, 369 } { 370 if added := rg.Add(r); !added { 371 t.Errorf("added new range %v to empty range group, wanted true added flag; got false", r) 372 } 373 } 374 375 tests := []struct { 376 r Range 377 want bool 378 }{ 379 { 380 r: Range{Start: []byte{0x0a}, End: []byte{0x0b}}, 381 want: true, 382 }, 383 { 384 r: Range{Start: []byte{0x01}, End: []byte{0x04}}, 385 want: true, 386 }, 387 { 388 r: Range{Start: []byte{0x04}, End: []byte{0x07}}, 389 want: true, 390 }, 391 { 392 r: Range{Start: []byte{0x06}, End: []byte{0x07}}, 393 want: false, 394 }, 395 { 396 r: Range{Start: []byte{0x05}, End: []byte{0x07}}, 397 want: false, 398 }, 399 { 400 r: Range{Start: []byte{0x05}, End: []byte{0x06}}, 401 want: false, 402 }, 403 { 404 r: Range{Start: []byte{0x05}, End: []byte{0x08}}, 405 want: true, 406 }, 407 { 408 r: Range{Start: []byte{0x01}, End: []byte{0x0f}}, 409 want: true, 410 }, 411 { 412 r: Range{Start: []byte{0x10}, End: []byte{0x11}}, 413 want: false, 414 }, 415 } 416 417 for _, test := range tests { 418 if enc := rg.Overlaps(test.r); enc != test.want { 419 t.Errorf("testing if range group %v overlaps range %v, wanted %t; got %t", rg, test.r, test.want, enc) 420 } 421 } 422 }) 423 } 424 425 func TestRangeGroupEnclosesRange(t *testing.T) { 426 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 427 for _, r := range []Range{ 428 {Start: []byte{0x01}, End: []byte{0x05}}, 429 {Start: []byte{0x07}, End: []byte{0x0f}}, 430 } { 431 if added := rg.Add(r); !added { 432 t.Errorf("added new range %v to empty range group, wanted true added flag; got false", r) 433 } 434 } 435 436 tests := []struct { 437 r Range 438 want bool 439 }{ 440 { 441 r: Range{Start: []byte{0x10}, End: []byte{0x11}}, 442 want: false, 443 }, 444 { 445 r: Range{Start: []byte{0x01}, End: []byte{0x04}}, 446 want: true, 447 }, 448 { 449 r: Range{Start: []byte{0x01}, End: []byte{0x05}}, 450 want: true, 451 }, 452 { 453 r: Range{Start: []byte{0x01}, End: []byte{0x0f}}, 454 want: false, 455 }, 456 { 457 r: Range{Start: []byte{0x07}, End: []byte{0x0f}}, 458 want: true, 459 }, 460 } 461 462 for _, test := range tests { 463 if enc := rg.Encloses(test.r); enc != test.want { 464 t.Errorf("testing if range group %v encloses range %v, wanted %t; got %t", rg, test.r, test.want, enc) 465 } 466 } 467 }) 468 } 469 470 func TestRangeGroupForEach(t *testing.T) { 471 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 472 errToThrow := errors.New("this error should be thrown") 473 dontErr := -1 474 tests := []struct { 475 rngs []Range 476 errAfter int // after this many iterations, throw error. -1 to ignore. 477 }{ 478 { 479 rngs: []Range{}, 480 errAfter: dontErr, 481 }, 482 { 483 rngs: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 484 errAfter: dontErr, 485 }, 486 { 487 rngs: []Range{ 488 {Start: []byte{0x01}, End: []byte{0x05}}, 489 {Start: []byte{0x09}, End: []byte{0xff}}, 490 }, 491 errAfter: dontErr, 492 }, 493 { 494 rngs: []Range{ 495 {Start: []byte{0x01}, End: []byte{0x05}}, 496 {Start: []byte{0x09}, End: []byte{0x10}}, 497 {Start: []byte{0x1a}, End: []byte{0x1c}}, 498 {Start: []byte{0x44}, End: []byte{0xf0}}, 499 {Start: []byte{0xf1}, End: []byte{0xff}}, 500 }, 501 errAfter: dontErr, 502 }, 503 { 504 rngs: []Range{ 505 {Start: []byte{0x01}, End: []byte{0x05}}, 506 {Start: []byte{0x09}, End: []byte{0x10}}, 507 {Start: []byte{0x1a}, End: []byte{0x1c}}, 508 {Start: []byte{0x44}, End: []byte{0xf0}}, 509 {Start: []byte{0xf1}, End: []byte{0xff}}, 510 }, 511 errAfter: 1, 512 }, 513 } 514 515 for _, test := range tests { 516 rg.Clear() 517 for _, r := range test.rngs { 518 rg.Add(r) 519 } 520 521 n := 0 522 acc := []Range{} 523 throwingErr := test.errAfter != -1 524 errSaw := rg.ForEach(func(r Range) error { 525 if throwingErr && n >= test.errAfter { 526 return errToThrow 527 } 528 n++ 529 acc = append(acc, r) 530 return nil 531 }) 532 533 expRngs := test.rngs 534 if throwingErr { 535 expRngs = test.rngs[:test.errAfter] 536 if !errors.Is(errSaw, errToThrow) { 537 t.Errorf("expected error %v from RangeGroup.ForEach, found %v", errToThrow, errSaw) 538 } 539 } else { 540 if errSaw != nil { 541 t.Errorf("no error expected from RangeGroup.ForEach, found %v", errSaw) 542 } 543 } 544 if !reflect.DeepEqual(acc, expRngs) { 545 t.Errorf("expected to accumulate Ranges %v, found %v", expRngs, acc) 546 } 547 } 548 }) 549 } 550 551 func TestRangeGroupIterator(t *testing.T) { 552 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 553 tests := []struct { 554 rngs []Range 555 }{ 556 { 557 rngs: []Range{}, 558 }, 559 { 560 rngs: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 561 }, 562 { 563 rngs: []Range{ 564 {Start: []byte{0x01}, End: []byte{0x05}}, 565 {Start: []byte{0x09}, End: []byte{0xff}}, 566 }, 567 }, 568 { 569 rngs: []Range{ 570 {Start: []byte{0x01}, End: []byte{0x05}}, 571 {Start: []byte{0x09}, End: []byte{0x10}}, 572 {Start: []byte{0x1a}, End: []byte{0x1c}}, 573 {Start: []byte{0x44}, End: []byte{0xf0}}, 574 {Start: []byte{0xf1}, End: []byte{0xff}}, 575 }, 576 }, 577 } 578 579 for _, test := range tests { 580 rg.Clear() 581 for _, r := range test.rngs { 582 rg.Add(r) 583 } 584 585 acc := []Range{} 586 it := rg.Iterator() 587 for r, ok := it.Next(); ok; r, ok = it.Next() { 588 acc = append(acc, r) 589 } 590 591 if !reflect.DeepEqual(acc, test.rngs) { 592 t.Errorf("expected to accumulate Ranges %v, found %v", test.rngs, acc) 593 } 594 } 595 }) 596 } 597 598 func TestRangeGroupStringer(t *testing.T) { 599 forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) { 600 tests := []struct { 601 rngs []Range 602 str string 603 }{ 604 { 605 rngs: []Range{}, 606 str: "[]", 607 }, 608 { 609 rngs: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 610 str: "[{01-05}]", 611 }, 612 { 613 rngs: []Range{ 614 {Start: []byte{0x01}, End: []byte{0x05}}, 615 {Start: []byte{0x09}, End: []byte{0xff}}, 616 }, 617 str: "[{01-05} {09-ff}]", 618 }, 619 { 620 rngs: []Range{ 621 {Start: []byte{0x01}, End: []byte{0x05}}, 622 {Start: []byte{0x09}, End: []byte{0xf0}}, 623 {Start: []byte{0xf1}, End: []byte{0xff}}, 624 }, 625 str: "[{01-05} {09-f0} {f1-ff}]", 626 }, 627 } 628 629 for _, test := range tests { 630 rg.Clear() 631 for _, r := range test.rngs { 632 rg.Add(r) 633 } 634 if str := rg.String(); str != test.str { 635 t.Errorf("added new ranges %v to range group, wanted string value %s; got %s", test.rngs, test.str, str) 636 } 637 } 638 }) 639 } 640 641 func TestRangeGroupsOverlap(t *testing.T) { 642 forEachRangeGroupImpl(t, func(t *testing.T, rg1 RangeGroup) { 643 forEachRangeGroupImpl(t, func(t *testing.T, rg2 RangeGroup) { 644 tests := []struct { 645 rngs1 []Range 646 rngs2 []Range 647 overlap bool 648 }{ 649 { 650 rngs1: []Range{}, 651 rngs2: []Range{}, 652 overlap: false, 653 }, 654 { 655 rngs1: []Range{}, 656 rngs2: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 657 overlap: false, 658 }, 659 { 660 rngs1: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 661 rngs2: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 662 overlap: true, 663 }, 664 { 665 rngs1: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 666 rngs2: []Range{{Start: []byte{0x05}, End: []byte{0x08}}}, 667 overlap: false, 668 }, 669 { 670 rngs1: []Range{{Start: []byte{0x01}, End: []byte{0x05}}}, 671 rngs2: []Range{{Start: []byte{0x04}, End: []byte{0x08}}}, 672 overlap: true, 673 }, 674 { 675 rngs1: []Range{ 676 {Start: []byte{0x01}, End: []byte{0x05}}, 677 {Start: []byte{0x09}, End: []byte{0xf0}}, 678 }, 679 rngs2: []Range{{Start: []byte{0xf1}, End: []byte{0xff}}}, 680 overlap: false, 681 }, 682 { 683 rngs1: []Range{ 684 {Start: []byte{0x01}, End: []byte{0x05}}, 685 {Start: []byte{0x09}, End: []byte{0xf0}}, 686 }, 687 rngs2: []Range{{Start: []byte{0xe0}, End: []byte{0xff}}}, 688 overlap: true, 689 }, 690 { 691 rngs1: []Range{ 692 {Start: []byte{0x01}, End: []byte{0x05}}, 693 {Start: []byte{0x09}, End: []byte{0x10}}, 694 {Start: []byte{0x1a}, End: []byte{0x1c}}, 695 {Start: []byte{0x44}, End: []byte{0xf0}}, 696 {Start: []byte{0xf1}, End: []byte{0xff}}, 697 }, 698 rngs2: []Range{{Start: []byte{0x11}, End: []byte{0x19}}}, 699 overlap: false, 700 }, 701 { 702 rngs1: []Range{ 703 {Start: []byte{0x01}, End: []byte{0x05}}, 704 {Start: []byte{0x09}, End: []byte{0x10}}, 705 {Start: []byte{0x1a}, End: []byte{0x1c}}, 706 {Start: []byte{0x44}, End: []byte{0xf0}}, 707 {Start: []byte{0xf1}, End: []byte{0xff}}, 708 }, 709 rngs2: []Range{{Start: []byte{0x11}, End: []byte{0xff}}}, 710 overlap: true, 711 }, 712 } 713 714 for _, test := range tests { 715 for _, swap := range []bool{false, true} { 716 rg1.Clear() 717 rg2.Clear() 718 719 rngs1, rngs2 := test.rngs1, test.rngs2 720 if swap { 721 rngs1, rngs2 = rngs2, rngs1 722 } 723 724 for _, r := range rngs1 { 725 rg1.Add(r) 726 } 727 for _, r := range rngs2 { 728 rg2.Add(r) 729 } 730 731 overlap := RangeGroupsOverlap(rg1, rg2) 732 if e, a := test.overlap, overlap; a != e { 733 t.Errorf("expected RangeGroupsOverlap(%s, %s) = %t, found %t", rg1, rg2, e, a) 734 } 735 } 736 } 737 }) 738 }) 739 } 740 741 func TestRangeListAndRangeGroupIdentical(t *testing.T) { 742 const trials = 5 743 for tr := 0; tr < trials; tr++ { 744 rl := NewRangeList() 745 rt := NewRangeTree() 746 747 const iters = 50 748 const nBytes = 2 749 for i := 0; i < iters; i++ { 750 lStr := rl.String() 751 tStr := rt.String() 752 if lStr != tStr { 753 t.Errorf("expected string value for RangeList and RangeTree to be the same; got %s for RangeList and %s for RangeTree", lStr, tStr) 754 } 755 756 ar := getRandomRange(t, nBytes) 757 listAdded := rl.Add(ar) 758 treeAdded := rt.Add(ar) 759 if listAdded != treeAdded { 760 t.Errorf("expected adding %s to RangeList %v and RangeTree %v to produce the same result; got %t from RangeList and %t from RangeTree", ar, rl, rt, listAdded, treeAdded) 761 } 762 763 sr := getRandomRange(t, nBytes) 764 listSubtracted := rl.Sub(sr) 765 treeSubtracted := rt.Sub(sr) 766 if listSubtracted != treeSubtracted { 767 t.Errorf("expected subtracting %s from RangeList %v and RangeTree %v to produce the same result; got %t from RangeList and %t from RangeTree", sr, rl, rt, listSubtracted, treeSubtracted) 768 } 769 770 or := getRandomRange(t, nBytes) 771 listOverlaps := rl.Overlaps(or) 772 treeOverlaps := rt.Overlaps(or) 773 if listOverlaps != treeOverlaps { 774 t.Errorf("expected RangeList %v and RangeTree %v to return the same overlapping state for %v; got %t from RangeList and %t from RangeTree", rl, rt, or, listOverlaps, treeOverlaps) 775 } 776 777 er := getRandomRange(t, nBytes) 778 listEncloses := rl.Encloses(er) 779 treeEncloses := rt.Encloses(er) 780 if listEncloses != treeEncloses { 781 t.Errorf("expected RangeList %v and RangeTree %v to return the same enclosing state for %v; got %t from RangeList and %t from RangeTree", rl, rt, er, listEncloses, treeEncloses) 782 } 783 784 listLen := rl.Len() 785 treeLen := rt.Len() 786 if listLen != treeLen { 787 t.Fatalf("expected RangeList and RangeTree to have the same length; got %d from RangeList and %d from RangeTree", listLen, treeLen) 788 } 789 790 listRngs := make([]Range, 0, rl.Len()) 791 treeRngs := make([]Range, 0, rt.Len()) 792 if err := rl.ForEach(func(r Range) error { 793 listRngs = append(listRngs, r) 794 return nil 795 }); err != nil { 796 t.Fatal(err) 797 } 798 if err := rt.ForEach(func(r Range) error { 799 treeRngs = append(treeRngs, r) 800 return nil 801 }); err != nil { 802 t.Fatal(err) 803 } 804 805 if !reflect.DeepEqual(listRngs, treeRngs) { 806 t.Fatalf("expected RangeList and RangeTree to contain the same ranges:\nstarted with %s\nadded %v\nsubtracted %v\n\ngot:\nRangeList: %v\nRangeTree: %v", lStr, ar, sr, rl, rt) 807 } 808 } 809 } 810 } 811 812 func getRandomRange(t *testing.T, n int) Range { 813 s1 := getRandomByteSlice(t, n) 814 s2 := getRandomByteSlice(t, n) 815 cmp := bytes.Compare(s1, s2) 816 for cmp == 0 { 817 s2 = getRandomByteSlice(t, n) 818 cmp = bytes.Compare(s1, s2) 819 } 820 if cmp < 0 { 821 return Range{Start: s1, End: s2} 822 } 823 return Range{Start: s2, End: s1} 824 } 825 826 func getRandomByteSlice(t *testing.T, n int) []byte { 827 s := make([]byte, n) 828 _, err := rand.Read(s) 829 if err != nil { 830 t.Fatalf("could not create random byte slice: %v", err) 831 } 832 return s 833 } 834 835 func BenchmarkRangeList(b *testing.B) { 836 benchmarkRangeGroup(b, NewRangeList()) 837 } 838 839 func BenchmarkRangeTree(b *testing.B) { 840 benchmarkRangeGroup(b, NewRangeTree()) 841 } 842 843 func benchmarkRangeGroup(b *testing.B, rg RangeGroup) { 844 for i := 0; i < b.N; i++ { 845 rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}) 846 rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}) 847 rg.Add(Range{Start: []byte{0x00}, End: []byte{0x02}}) 848 rg.Add(Range{Start: []byte{0x01}, End: []byte{0x06}}) 849 rg.Add(Range{Start: []byte{0x05}, End: []byte{0x15}}) 850 rg.Add(Range{Start: []byte{0x25}, End: []byte{0x30}}) 851 rg.Clear() 852 } 853 }