@@ -587,4 +587,121 @@ final class HeapTests: CollectionTestCase {
587587 }
588588 }
589589 }
590+
591+ struct Distinguishable : Comparable , CustomStringConvertible {
592+ var value : Int
593+ var id : Int
594+
595+ static func == ( left: Self , right: Self ) -> Bool {
596+ left. value == right. value
597+ }
598+ static func < ( left: Self , right: Self ) -> Bool {
599+ left. value < right. value
600+ }
601+ var description : String { " \( value) / \( id) " }
602+ }
603+
604+ func test_tieBreaks_min( ) {
605+ var heap : Heap = [
606+ Distinguishable ( value: 1 , id: 1 ) ,
607+ Distinguishable ( value: 1 , id: 2 ) ,
608+ Distinguishable ( value: 1 , id: 3 ) ,
609+ Distinguishable ( value: 1 , id: 4 ) ,
610+ Distinguishable ( value: 1 , id: 5 ) ,
611+ ]
612+ while !heap. isEmpty {
613+ let oldID = heap. min!. id
614+ let newID = 10 * oldID
615+ let old = heap. replaceMin ( with: Distinguishable ( value: 1 , id: newID) )
616+ expectEqual ( old. id, oldID)
617+ expectEqual ( heap. min? . id, 10 * oldID)
618+ expectNotNil ( heap. removeMin ( ) ) { min in
619+ expectEqual ( min. id, newID)
620+ }
621+ }
622+ }
623+
624+ func test_tieBreaks_max( ) {
625+ var heap : Heap = [
626+ Distinguishable ( value: 1 , id: 1 ) ,
627+ Distinguishable ( value: 1 , id: 2 ) ,
628+ Distinguishable ( value: 1 , id: 3 ) ,
629+ Distinguishable ( value: 1 , id: 4 ) ,
630+ Distinguishable ( value: 1 , id: 5 ) ,
631+ ]
632+ while !heap. isEmpty {
633+ let oldID = heap. max!. id
634+ let newID = 10 * oldID
635+ print ( heap. unordered)
636+ let old = heap. replaceMax ( with: Distinguishable ( value: 1 , id: newID) )
637+ expectEqual ( old. id, oldID)
638+ expectEqual ( heap. max? . id, 10 * oldID)
639+ expectNotNil ( heap. removeMax ( ) ) { max in
640+ expectEqual ( max. id, newID)
641+ }
642+ }
643+ }
644+
645+ func test_removeAll_noneRemoved( ) {
646+ withEvery ( " count " , in: 0 ..< 20 ) { count in
647+ withEvery ( " seed " , in: 0 ..< 10 ) { seed in
648+ var rng = RepeatableRandomNumberGenerator ( seed: seed)
649+ let input = ( 0 ..< count) . shuffled ( using: & rng)
650+ var heap = Heap ( input)
651+ heap. removeAll { _ in false }
652+ let expected = Array ( 0 ..< count)
653+ expectEqualElements ( heap. itemsInAscendingOrder ( ) , expected)
654+ }
655+ }
656+ }
657+
658+ func test_removeAll_allRemoved( ) {
659+ withEvery ( " count " , in: 0 ..< 20 ) { count in
660+ withEvery ( " seed " , in: 0 ..< 10 ) { seed in
661+ var rng = RepeatableRandomNumberGenerator ( seed: seed)
662+ let input = ( 0 ..< count) . shuffled ( using: & rng)
663+ var heap = Heap ( input)
664+ heap. removeAll { _ in true }
665+ expectTrue ( heap. isEmpty)
666+ }
667+ }
668+ }
669+
670+ func test_removeAll_removeEvenNumbers( ) {
671+ withEvery ( " count " , in: 0 ..< 20 ) { count in
672+ withEvery ( " seed " , in: 0 ..< 10 ) { seed in
673+ var rng = RepeatableRandomNumberGenerator ( seed: seed)
674+ let input = ( 0 ..< count) . shuffled ( using: & rng)
675+ var heap = Heap ( input)
676+ heap. removeAll { $0 % 2 == 0 }
677+ let expected = Array ( stride ( from: 1 , to: count, by: 2 ) )
678+ expectEqualElements ( heap. itemsInAscendingOrder ( ) , expected)
679+ }
680+ }
681+ }
682+
683+ func test_removeAll_throw( ) throws {
684+ struct DummyError : Error { }
685+
686+ try withEvery ( " count " , in: 1 ..< 20 ) { count in
687+ try withEvery ( " seed " , in: 0 ..< 10 ) { seed in
688+ var rng = RepeatableRandomNumberGenerator ( seed: seed)
689+ let input = ( 0 ..< count) . shuffled ( using: & rng)
690+ var heap = Heap ( input)
691+ expectThrows (
692+ try heap. removeAll { v in
693+ if v == count / 2 {
694+ throw DummyError ( )
695+ }
696+ return v % 2 == 0
697+ }
698+ ) { error in
699+ expectTrue ( error is DummyError )
700+ }
701+ // Throwing halfway through `removeAll` is expected to reorder items,
702+ // but not remove any.
703+ expectEqualElements ( heap. itemsInAscendingOrder ( ) , 0 ..< count)
704+ }
705+ }
706+ }
590707}
0 commit comments