1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2020 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import XCTest
@testable import NIO
class PriorityQueueTest: XCTestCase {
func testSomeStringsAsc() throws {
var pq = PriorityQueue<String>()
pq.push("foo")
pq.push("bar")
pq.push("buz")
pq.push("qux")
pq.remove("buz")
XCTAssertEqual("bar", pq.peek()!)
XCTAssertEqual("bar", pq.pop()!)
pq.push("bar")
XCTAssertEqual("bar", pq.peek()!)
XCTAssertEqual("bar", pq.pop()!)
XCTAssertEqual("foo", pq.pop()!)
XCTAssertEqual("qux", pq.pop()!)
XCTAssertTrue(pq.isEmpty)
}
func testRemoveNonExisting() throws {
var pq = PriorityQueue<String>()
pq.push("foo")
pq.remove("bar")
pq.remove("foo")
XCTAssertNil(pq.pop())
XCTAssertNil(pq.peek())
}
func testRemoveFromEmpty() throws {
var pq = PriorityQueue<Int>()
pq.remove(234)
XCTAssertTrue(pq.isEmpty)
}
func testBuildAndRemoveFromRandomPriorityQueues() {
for size in 0...33 {
var pq = PriorityQueue<UInt8>()
let randoms = getRandomNumbers(count: size)
randoms.forEach { pq.push($0) }
/* remove one random member, add it back and assert we're still the same */
randoms.forEach { random in
var pq2 = pq
pq2.remove(random)
XCTAssertEqual(pq.count - 1, pq2.count)
XCTAssertNotEqual(pq, pq2)
pq2.push(random)
XCTAssertEqual(pq, pq2)
}
/* remove up to `n` members and add them back at the end and check that the priority queues are still the same */
for n in 1...5 where n <= size {
var pq2 = pq
let deleted = randoms.prefix(n).map { (random: UInt8) -> UInt8 in
pq2.remove(random)
return random
}
XCTAssertEqual(pq.count - n, pq2.count)
XCTAssertNotEqual(pq, pq2)
deleted.reversed().forEach { pq2.push($0) }
XCTAssertEqual(pq, pq2, "pq: \(pq), pq2: \(pq2), deleted: \(deleted)")
}
}
}
func testPartialOrder() {
let clearlyTheSmallest = SomePartiallyOrderedDataType(width: 0, height: 0)
let clearlyTheLargest = SomePartiallyOrderedDataType(width: 100, height: 100)
let inTheMiddles = zip(1...99, (1...99).reversed()).map { SomePartiallyOrderedDataType(width: $0, height: $1) }
/*
the four values are only partially ordered (from small (top) to large (bottom)):
clearlyTheSmallest
/ | \
inTheMiddle[0] | inTheMiddle[1...]
\ | /
clearlyTheLargest
*/
var pq = PriorityQueue<SomePartiallyOrderedDataType>()
pq.push(clearlyTheLargest)
pq.push(inTheMiddles[0])
pq.push(clearlyTheSmallest)
inTheMiddles[1...].forEach {
pq.push($0)
}
let pop1 = pq.pop()
XCTAssertEqual(clearlyTheSmallest, pop1)
for _ in inTheMiddles {
let popN = pq.pop()!
XCTAssert(inTheMiddles.contains(popN))
}
XCTAssertEqual(clearlyTheLargest, pq.pop()!)
XCTAssert(pq.isEmpty)
}
func testDescription() {
let pq1 = PriorityQueue<Int>()
var pq2 = PriorityQueue<Int>()
pq2.push(1)
pq2.push(2)
pq2.push(3)
XCTAssertEqual(pq1.description, "PriorityQueue(count: 0): \(Array(pq1))")
XCTAssertEqual(pq2.description, "PriorityQueue(count: 3): \(Array(pq2))")
}
}
/// This data type is only partially ordered. Ie. from `a < b` and `a != b` we can't imply `a > b`.
struct SomePartiallyOrderedDataType: Comparable, CustomStringConvertible {
public static func <(lhs: SomePartiallyOrderedDataType, rhs: SomePartiallyOrderedDataType) -> Bool {
return lhs.width < rhs.width && lhs.height < rhs.height
}
public static func ==(lhs: SomePartiallyOrderedDataType, rhs: SomePartiallyOrderedDataType) -> Bool {
return lhs.width == rhs.width && lhs.height == rhs.height
}
private let width: Int
private let height: Int
public init(width: Int, height: Int) {
self.width = width
self.height = height
}
public var description: String {
return "(w: \(self.width), h: \(self.height))"
}
}
|