Skip to content

Commit

Permalink
Merge pull request swiftlang#1366 from millenomi/pr/concurrent-nsarra…
Browse files Browse the repository at this point in the history
…y-take2
  • Loading branch information
swift-ci authored Dec 12, 2017
2 parents fed31bc + b124e68 commit 7bf5fc7
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 4 deletions.
4 changes: 0 additions & 4 deletions Foundation/NSIndexSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -377,10 +377,6 @@ open class NSIndexSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
}

internal func _enumerateWithOptions<P, R>(_ opts : NSEnumerationOptions, range: NSRange, paramType: P.Type, returnType: R.Type, block: (P, UnsafeMutablePointer<ObjCBool>) -> R) -> Int? {
guard !opts.contains(.concurrent) else {
NSUnimplemented()
}

guard let startRangeIndex = self._indexOfRangeAfterOrContainingIndex(range.location), let endRangeIndex = _indexOfRangeBeforeOrContainingIndex(NSMaxRange(range) - 1) else {
return nil
}
Expand Down
122 changes: 122 additions & 0 deletions TestFoundation/TestNSArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class TestNSArray : XCTestCase {
("test_constructors", test_constructors),
("test_constructorWithCopyItems", test_constructorWithCopyItems),
("test_enumeration", test_enumeration),
("test_enumerationUsingBlock", test_enumerationUsingBlock),
("test_sequenceType", test_sequenceType),
("test_objectAtIndex", test_objectAtIndex),
("test_binarySearch", test_binarySearch),
Expand Down Expand Up @@ -123,6 +124,127 @@ class TestNSArray : XCTestCase {
XCTAssertNil(reverseEmpty.nextObject())
}

func test_enumerationUsingBlock() {
let array : NSArray = NSArray(array: Array(0..<100))
let createIndexesArrayHavingSeen = { (havingSeen: IndexSet) in
return (0 ..< array.count).map { havingSeen.contains($0) }
}

let noIndexes = IndexSet()
let allIndexes = IndexSet(integersIn: 0 ..< array.count)
let firstHalfOfIndexes = IndexSet(integersIn: 0 ..< array.count / 2)
let lastHalfOfIndexes = IndexSet(integersIn: array.count / 2 ..< array.count)
let evenIndexes : IndexSet = {
var indexes = IndexSet()
for index in allIndexes.filter({ $0 % 2 == 0 }) {
indexes.insert(index)
}
return indexes
}()

let testExpectingToSee = { (expectation: IndexSet, block: (inout UnsafeMutableBufferPointer<Bool>) -> Void) in
var indexesSeen = createIndexesArrayHavingSeen(noIndexes)
indexesSeen.withUnsafeMutableBufferPointer(block)
XCTAssertEqual(indexesSeen, createIndexesArrayHavingSeen(expectation))
}

// Test enumerateObjects(_:), allowing it to run to completion...

testExpectingToSee(allIndexes) { (indexesSeen) in
array.enumerateObjects { (value, index, stop) in
XCTAssertEqual(value as! NSNumber, array[index] as! NSNumber)
indexesSeen[index] = true
}
}

// ... and stopping after the first half:

testExpectingToSee(firstHalfOfIndexes) { (indexesSeen) in
array.enumerateObjects { (value, index, stop) in
XCTAssertEqual(value as! NSNumber, array[index] as! NSNumber)

if firstHalfOfIndexes.contains(index) {
indexesSeen[index] = true
} else {
stop.pointee = true
}
}
}

// -----
// Test enumerateObjects(options:using) and enumerateObjects(at:options:using:):

// Test each of these options combinations:
let optionsToTest : [NSEnumerationOptions] = [
[],
[.concurrent],
[.reverse],
[.concurrent, .reverse],
]

for options in optionsToTest {
// Run to completion,
testExpectingToSee(allIndexes) { (indexesSeen) in
array.enumerateObjects(options: options, using: { (value, index, stop) in
XCTAssertEqual(value as! NSNumber, array[index] as! NSNumber)
indexesSeen[index] = true
})
}

// run it only for half the indexes (use the right half depending on where we start),
let indexesForHalfEnumeration = options.contains(.reverse) ? lastHalfOfIndexes : firstHalfOfIndexes

testExpectingToSee(indexesForHalfEnumeration) { (indexesSeen) in
array.enumerateObjects(options: options, using: { (value, index, stop) in
XCTAssertEqual(value as! NSNumber, array[index] as! NSNumber)

if indexesForHalfEnumeration.contains(index) {
indexesSeen[index] = true
} else {
stop.pointee = true
}
})
}

// run only for a specific index set to test the at:… variant,
testExpectingToSee(evenIndexes) { (indexesSeen) in
array.enumerateObjects(at: evenIndexes, options: options, using: { (value, index, stop) in
XCTAssertEqual(value as! NSNumber, array[index] as! NSNumber)
indexesSeen[index] = true
})
}

// and run for some indexes only to test stopping.
var indexesForStaggeredEnumeration = indexesForHalfEnumeration
indexesForStaggeredEnumeration.formIntersection(evenIndexes)

let finalCount = indexesForStaggeredEnumeration.count

let lockForSeenCount = NSLock()
var seenCount = 0

testExpectingToSee(indexesForStaggeredEnumeration) { (indexesSeen) in
array.enumerateObjects(at: evenIndexes, options: options, using: { (value, index, stop) in
XCTAssertEqual(value as! NSNumber, array[index] as! NSNumber)

if (indexesForStaggeredEnumeration.contains(index)) {
indexesSeen[index] = true

lockForSeenCount.lock()
seenCount += 1
let currentCount = seenCount
lockForSeenCount.unlock()

if currentCount == finalCount {
stop.pointee = true
}
}
})
}
}

}

func test_sequenceType() {
let array : NSArray = ["foo", "bar", "baz"]
var res = [String]()
Expand Down

0 comments on commit 7bf5fc7

Please sign in to comment.