From a51ef3e3c9174d0cb6aa60a9fd6c31fe722fb435 Mon Sep 17 00:00:00 2001 From: Kevin Lundberg Date: Thu, 10 Dec 2015 22:50:50 -0500 Subject: [PATCH] Add block/boolean NSPredicates, NSCompoundPredicate, and NSArray predicate method --- Foundation.xcodeproj/project.pbxproj | 24 ++-- Foundation/NSCompoundPredicate.swift | 43 +++++-- Foundation/NSPredicate.swift | 46 ++++++-- TestFoundation/TestNSCompoundPredicate.swift | 118 +++++++++++++++++++ TestFoundation/TestNSPredicate.swift | 57 +++++++++ TestFoundation/main.swift | 6 +- 6 files changed, 270 insertions(+), 24 deletions(-) create mode 100644 TestFoundation/TestNSCompoundPredicate.swift create mode 100644 TestFoundation/TestNSPredicate.swift diff --git a/Foundation.xcodeproj/project.pbxproj b/Foundation.xcodeproj/project.pbxproj index 279e2074aa..91957ffe74 100755 --- a/Foundation.xcodeproj/project.pbxproj +++ b/Foundation.xcodeproj/project.pbxproj @@ -254,6 +254,8 @@ 61E011811C1B5998000037DD /* CFMessagePort.c in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D88DC1BBC9AEC00234F36 /* CFMessagePort.c */; }; 61E011821C1B599A000037DD /* CFMachPort.c in Sources */ = {isa = PBXBuildFile; fileRef = 5B5D88D01BBC9AAC00234F36 /* CFMachPort.c */; }; AE35A1861CBAC85E0042DB84 /* SwiftFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = AE35A1851CBAC85E0042DB84 /* SwiftFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7900433B1CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */; }; + 7900433C1CACD33E00ECCBF1 /* TestNSPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7900433A1CACD33E00ECCBF1 /* TestNSPredicate.swift */; }; CE19A88C1C23AA2300B4CB6A /* NSStringTestData.txt in Resources */ = {isa = PBXBuildFile; fileRef = CE19A88B1C23AA2300B4CB6A /* NSStringTestData.txt */; }; D31302011C30CEA900295652 /* NSConcreteValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D31302001C30CEA900295652 /* NSConcreteValue.swift */; }; D370696E1C394FBF00295652 /* NSKeyedUnarchiver-RangeTest.plist in Resources */ = {isa = PBXBuildFile; fileRef = D370696D1C394FBF00295652 /* NSKeyedUnarchiver-RangeTest.plist */; }; @@ -547,15 +549,15 @@ 5B5D89A51BBDC06800234F36 /* CFStringEncodingDatabase.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFStringEncodingDatabase.c; sourceTree = ""; }; 5B5D89A71BBDC09700234F36 /* CFStringScanner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFStringScanner.c; sourceTree = ""; }; 5B5D89A91BBDC11100234F36 /* CFLocaleKeys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFLocaleKeys.c; sourceTree = ""; }; + 5B6228BA1C179041009587FE /* CFRunArray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFRunArray.c; sourceTree = ""; }; + 5B6228BC1C179049009587FE /* CFRunArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFRunArray.h; sourceTree = ""; }; + 5B6228BE1C179052009587FE /* CFAttributedString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFAttributedString.c; sourceTree = ""; }; + 5B6228C01C17905B009587FE /* CFAttributedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFAttributedString.h; sourceTree = ""; }; 5B6F17921C48631C00935030 /* TestNSNull.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSNull.swift; sourceTree = ""; }; 5B6F17931C48631C00935030 /* TestNSNumberFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSNumberFormatter.swift; sourceTree = ""; }; 5B6F17941C48631C00935030 /* TestNSTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSTask.swift; sourceTree = ""; }; 5B6F17951C48631C00935030 /* TestNSXMLDocument.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSXMLDocument.swift; sourceTree = ""; }; 5B6F17961C48631C00935030 /* TestUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = ""; }; - 5B6228BA1C179041009587FE /* CFRunArray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFRunArray.c; sourceTree = ""; }; - 5B6228BC1C179049009587FE /* CFRunArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFRunArray.h; sourceTree = ""; }; - 5B6228BE1C179052009587FE /* CFAttributedString.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFAttributedString.c; sourceTree = ""; }; - 5B6228C01C17905B009587FE /* CFAttributedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFAttributedString.h; sourceTree = ""; }; 5B7C8A6E1BEA7F8F00C5B690 /* libCoreFoundation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCoreFoundation.a; sourceTree = BUILT_PRODUCTS_DIR; }; 5B94E8811C430DE70055C035 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; 5BC1D8BC1BF3ADFE009D3973 /* TestNSCharacterSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSCharacterSet.swift; sourceTree = ""; }; @@ -610,6 +612,8 @@ 61E0117B1C1B554D000037DD /* TestNSRunLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSRunLoop.swift; sourceTree = ""; }; 61F8AE7C1C180FC600FB62F0 /* TestNSNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSNotificationCenter.swift; sourceTree = ""; }; 6E203B8C1C1303BB003B2576 /* TestNSBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSBundle.swift; sourceTree = ""; }; + 790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSCompoundPredicate.swift; sourceTree = ""; }; + 7900433A1CACD33E00ECCBF1 /* TestNSPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSPredicate.swift; sourceTree = ""; }; 7A7D6FBA1C16439400957E2E /* TestNSURLResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSURLResponse.swift; sourceTree = ""; }; 83712C8D1C1684900049AD49 /* TestNSURLRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSURLRequest.swift; sourceTree = ""; }; 844DC3321C17584F005611F9 /* TestNSScanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSScanner.swift; sourceTree = ""; }; @@ -1159,10 +1163,13 @@ C93559281C12C49F009FD6A9 /* TestNSAffineTransform.swift */, EA66F63C1BF1619600136161 /* TestNSArray.swift */, 6E203B8C1C1303BB003B2576 /* TestNSBundle.swift */, + A5A34B551C18C85D00FD972B /* TestNSByteCountFormatter.swift */, 52829AD61C160D64003BC4EF /* TestNSCalendar.swift */, 5BC1D8BC1BF3ADFE009D3973 /* TestNSCharacterSet.swift */, + 790043391CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift */, DCDBB8321C1768AC00313299 /* TestNSData.swift */, 22B9C1E01C165D7A00DECFF9 /* TestNSDate.swift */, + 2EBE67A31C77BF05006583D5 /* TestNSDateFormatter.swift */, EA66F63D1BF1619600136161 /* TestNSDictionary.swift */, 525AECEB1BF2C96400D15BB0 /* TestNSFileManager.swift */, 88D28DE61C13AE9000494606 /* TestNSGeometry.swift */, @@ -1180,6 +1187,7 @@ 5B6F17931C48631C00935030 /* TestNSNumberFormatter.swift */, D834F9931C31C4060023812A /* TestNSOrderedSet.swift */, 4DC1D07F1C12EEEF00B5948A /* TestNSPipe.swift */, + 7900433A1CACD33E00ECCBF1 /* TestNSPredicate.swift */, 400E22641C1A4E58007C5933 /* TestNSProcessInfo.swift */, EA66F6401BF1619600136161 /* TestNSPropertyList.swift */, E876A73D1C1180E000F279EC /* TestNSRange.swift */, @@ -1195,15 +1203,13 @@ EA66F6431BF1619600136161 /* TestNSURL.swift */, 83712C8D1C1684900049AD49 /* TestNSURLRequest.swift */, 7A7D6FBA1C16439400957E2E /* TestNSURLResponse.swift */, + 555683BC1C1250E70041D4C6 /* TestNSUserDefaults.swift */, C2A9D75B1C15C08B00993803 /* TestNSUUID.swift */, + D3047AEB1C38BC3300295652 /* TestNSValue.swift */, 5B6F17951C48631C00935030 /* TestNSXMLDocument.swift */, 5B40F9F11C125187000E72E3 /* TestNSXMLParser.swift */, - 555683BC1C1250E70041D4C6 /* TestNSUserDefaults.swift */, 5B6F17961C48631C00935030 /* TestUtils.swift */, - A5A34B551C18C85D00FD972B /* TestNSByteCountFormatter.swift */, - D3047AEB1C38BC3300295652 /* TestNSValue.swift */, E19E17DB1C2225930023AF4D /* TestNSXMLDocument.swift */, - 2EBE67A31C77BF05006583D5 /* TestNSDateFormatter.swift */, ); name = Tests; sourceTree = ""; @@ -1952,6 +1958,7 @@ 5B13B33E1C582D4C00651CE2 /* TestNSProcessInfo.swift in Sources */, 5B13B33F1C582D4C00651CE2 /* TestNSPropertyList.swift in Sources */, 5B13B32C1C582D4C00651CE2 /* TestNSDate.swift in Sources */, + 7900433C1CACD33E00ECCBF1 /* TestNSPredicate.swift in Sources */, 5B13B33B1C582D4C00651CE2 /* TestNSNumberFormatter.swift in Sources */, 5B13B3301C582D4C00651CE2 /* TestNSHTTPCookie.swift in Sources */, 5B13B3361C582D4C00651CE2 /* TestNSLocale.swift in Sources */, @@ -1984,6 +1991,7 @@ 5B13B3271C582D4C00651CE2 /* TestNSArray.swift in Sources */, 5B13B3461C582D4C00651CE2 /* TestNSTask.swift in Sources */, 555683BD1C1250E70041D4C6 /* TestNSUserDefaults.swift in Sources */, + 7900433B1CACD33E00ECCBF1 /* TestNSCompoundPredicate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Foundation/NSCompoundPredicate.swift b/Foundation/NSCompoundPredicate.swift index b9ad668fdb..3f175740c8 100644 --- a/Foundation/NSCompoundPredicate.swift +++ b/Foundation/NSCompoundPredicate.swift @@ -19,14 +19,43 @@ public enum NSCompoundPredicateType : UInt { public class NSCompoundPredicate : NSPredicate { - public init(type: NSCompoundPredicateType, subpredicates: [NSPredicate]) { NSUnimplemented() } + public init(type: NSCompoundPredicateType, subpredicates: [NSPredicate]) { + if type == .NotPredicateType && subpredicates.count == 0 { + preconditionFailure("Unsupported predicate count of \(subpredicates.count) for \(type)") + } + self.compoundPredicateType = type + self.subpredicates = subpredicates + super.init(value: false) + } public required init?(coder: NSCoder) { NSUnimplemented() } - public var compoundPredicateType: NSCompoundPredicateType { NSUnimplemented() } - public var subpredicates: [AnyObject] { NSUnimplemented() } - + public let compoundPredicateType: NSCompoundPredicateType + public let subpredicates: [NSPredicate] + /*** Convenience Methods ***/ - public init(andPredicateWithSubpredicates subpredicates: [NSPredicate]) { NSUnimplemented() } - public init(orPredicateWithSubpredicates subpredicates: [NSPredicate]) { NSUnimplemented() } - public init(notPredicateWithSubpredicate predicate: NSPredicate) { NSUnimplemented() } + public convenience init(andPredicateWithSubpredicates subpredicates: [NSPredicate]) { + self.init(type: .AndPredicateType, subpredicates: subpredicates) + } + public convenience init(orPredicateWithSubpredicates subpredicates: [NSPredicate]) { + self.init(type: .OrPredicateType, subpredicates: subpredicates) + } + public convenience init(notPredicateWithSubpredicate predicate: NSPredicate) { + self.init(type: .NotPredicateType, subpredicates: [predicate]) + } + + override public func evaluateWithObject(_ object: AnyObject?, substitutionVariables bindings: [String : AnyObject]?) -> Bool { + switch compoundPredicateType { + case .AndPredicateType: + return subpredicates.reduce(true, combine: { + $0 && $1.evaluateWithObject(object, substitutionVariables: bindings) + }) + case .OrPredicateType: + return subpredicates.reduce(false, combine: { + $0 || $1.evaluateWithObject(object, substitutionVariables: bindings) + }) + case .NotPredicateType: + // safe to get the 0th item here since we trap if there's not at least one on init + return !(subpredicates[0].evaluateWithObject(object, substitutionVariables: bindings)) + } + } } diff --git a/Foundation/NSPredicate.swift b/Foundation/NSPredicate.swift index 8c52bcb3d4..b01f2cc7ba 100644 --- a/Foundation/NSPredicate.swift +++ b/Foundation/NSPredicate.swift @@ -11,7 +11,16 @@ // Predicates wrap some combination of expressions and operators and when evaluated return a BOOL. public class NSPredicate : NSObject, NSSecureCoding, NSCopying { - + + private enum PredicateKind { + case Boolean(Bool) + case Block((AnyObject?, [String : AnyObject]?) -> Bool) + // TODO: case for init(format:argumentArray:) + // TODO: case for init(fromMetadataQueryString:) + } + + private let kind: PredicateKind + public static func supportsSecureCoding() -> Bool { return true } @@ -37,23 +46,46 @@ public class NSPredicate : NSObject, NSSecureCoding, NSCopying { public init?(fromMetadataQueryString queryString: String) { NSUnimplemented() } - public init(value: Bool) { NSUnimplemented() } // return predicates that always evaluate to true/false - - public init(block: (AnyObject, [String : AnyObject]?) -> Bool) { NSUnimplemented() } + public init(value: Bool) { + kind = .Boolean(value) + super.init() + } // return predicates that always evaluate to true/false + + public init(block: (AnyObject?, [String : AnyObject]?) -> Bool) { + kind = .Block(block) + super.init() + } public var predicateFormat: String { NSUnimplemented() } // returns the format string of the predicate public func predicateWithSubstitutionVariables(_ variables: [String : AnyObject]) -> Self { NSUnimplemented() } // substitute constant values for variables - public func evaluateWithObject(_ object: AnyObject?) -> Bool { NSUnimplemented() } // evaluate a predicate against a single object + public func evaluateWithObject(_ object: AnyObject?) -> Bool { + return evaluateWithObject(object, substitutionVariables: nil) + } // evaluate a predicate against a single object - public func evaluateWithObject(_ object: AnyObject?, substitutionVariables bindings: [String : AnyObject]?) -> Bool { NSUnimplemented() } // single pass evaluation substituting variables from the bindings dictionary for any variable expressions encountered + public func evaluateWithObject(_ object: AnyObject?, substitutionVariables bindings: [String : AnyObject]?) -> Bool { + if bindings != nil { + NSUnimplemented() + } + + switch kind { + case let .Boolean(value): + return value + case let .Block(block): + return block(object, bindings) + } + } // single pass evaluation substituting variables from the bindings dictionary for any variable expressions encountered public func allowEvaluation() { NSUnimplemented() } // Force a predicate which was securely decoded to allow evaluation } extension NSArray { - public func filteredArrayUsingPredicate(_ predicate: NSPredicate) -> [AnyObject] { NSUnimplemented() } // evaluate a predicate against an array of objects and return a filtered array + public func filteredArrayUsingPredicate(_ predicate: NSPredicate) -> [AnyObject] { + return bridge().filter({ object in + return predicate.evaluateWithObject(object) + }) + } // evaluate a predicate against an array of objects and return a filtered array } extension NSMutableArray { diff --git a/TestFoundation/TestNSCompoundPredicate.swift b/TestFoundation/TestNSCompoundPredicate.swift new file mode 100644 index 0000000000..8d3b1c70e6 --- /dev/null +++ b/TestFoundation/TestNSCompoundPredicate.swift @@ -0,0 +1,118 @@ +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// + +#if DEPLOYMENT_RUNTIME_OBJC || os(Linux) + import Foundation + import XCTest +#else + import SwiftFoundation + import SwiftXCTest +#endif + +class TestNSCompoundPredicate: XCTestCase { + + static var allTests: [(String, TestNSCompoundPredicate -> () throws -> Void)] { + return [ + ("test_NotPredicate", test_NotPredicate), + ("test_AndPredicateWithNoSubpredicates", test_AndPredicateWithNoSubpredicates), + ("test_AndPredicateWithOneSubpredicate", test_AndPredicateWithOneSubpredicate), + ("test_AndPredicateWithMultipleSubpredicates", test_AndPredicateWithMultipleSubpredicates), + ("test_OrPredicateWithNoSubpredicates", test_OrPredicateWithNoSubpredicates), + ("test_OrPredicateWithOneSubpredicate", test_OrPredicateWithOneSubpredicate), + ("test_OrPredicateWithMultipleSubpredicates", test_OrPredicateWithMultipleSubpredicates), + ("test_OrPredicateShortCircuits", test_OrPredicateShortCircuits), + ("test_AndPredicateShortCircuits", test_AndPredicateShortCircuits), + ] + } + + private func eval(_ predicate: NSPredicate, object: NSObject = NSObject()) -> Bool { + return predicate.evaluateWithObject(object, substitutionVariables: nil) + } + + func test_NotPredicate() { + let notTruePredicate = NSCompoundPredicate(notPredicateWithSubpredicate: NSPredicate(value: true)) + let notFalsePredicate = NSCompoundPredicate(notPredicateWithSubpredicate: NSPredicate(value: false)) + + XCTAssertFalse(eval(notTruePredicate)) + XCTAssertTrue(eval(notFalsePredicate)) + } + + func test_AndPredicateWithNoSubpredicates() { + let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: []) + + XCTAssertTrue(eval(predicate)) + } + + func test_AndPredicateWithOneSubpredicate() { + let truePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(value: true)]) + let falsePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(value: false)]) + + XCTAssertTrue(eval(truePredicate)) + XCTAssertFalse(eval(falsePredicate)) + } + + func test_AndPredicateWithMultipleSubpredicates() { + let truePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(value: true), NSPredicate(value: true)]) + let falsePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(value: true), NSPredicate(value: false)]) + + XCTAssertTrue(eval(truePredicate)) + XCTAssertFalse(eval(falsePredicate)) + } + + + func test_OrPredicateWithNoSubpredicates() { + let predicate = NSCompoundPredicate(orPredicateWithSubpredicates: []) + + XCTAssertFalse(eval(predicate)) + } + + func test_OrPredicateWithOneSubpredicate() { + let truePredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [NSPredicate(value: true)]) + let falsePredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [NSPredicate(value: false)]) + + XCTAssertTrue(eval(truePredicate)) + XCTAssertFalse(eval(falsePredicate)) + } + + func test_OrPredicateWithMultipleSubpredicates() { + let truePredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [NSPredicate(value: true), NSPredicate(value: false)]) + let falsePredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [NSPredicate(value: false), NSPredicate(value: false)]) + + XCTAssertTrue(eval(truePredicate)) + XCTAssertFalse(eval(falsePredicate)) + } + + func test_AndPredicateShortCircuits() { + var shortCircuited = true + + let bOK = NSPredicate(value: false) + let bDontEval = NSPredicate(block: { _ in + shortCircuited = false + return true + }) + + let both = NSCompoundPredicate(andPredicateWithSubpredicates: [bOK, bDontEval]) + XCTAssertFalse(eval(both)) + XCTAssertTrue(shortCircuited) + } + + func test_OrPredicateShortCircuits() { + var shortCircuited = true + + let bOK = NSPredicate(value: true) + let bDontEval = NSPredicate(block: { _ in + shortCircuited = false + return true + }) + + let both = NSCompoundPredicate(orPredicateWithSubpredicates: [bOK, bDontEval]) + XCTAssertTrue(eval(both)) + XCTAssertTrue(shortCircuited) + } +} diff --git a/TestFoundation/TestNSPredicate.swift b/TestFoundation/TestNSPredicate.swift new file mode 100644 index 0000000000..70cdcac37b --- /dev/null +++ b/TestFoundation/TestNSPredicate.swift @@ -0,0 +1,57 @@ +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// + +#if DEPLOYMENT_RUNTIME_OBJC || os(Linux) + import Foundation + import XCTest +#else + import SwiftFoundation + import SwiftXCTest +#endif + +class TestNSPredicate: XCTestCase { + + static var allTests : [(String, TestNSPredicate -> () throws -> Void)] { + return [ + ("test_BooleanPredicate", test_BooleanPredicate), + ("test_BlockPredicateWithoutVariableBindings", test_BlockPredicateWithoutVariableBindings), + ("test_filterNSArray", test_filterNSArray), + ] + } + + func test_BooleanPredicate() { + let truePredicate = NSPredicate(value: true) + let falsePredicate = NSPredicate(value: false) + + XCTAssertTrue(truePredicate.evaluateWithObject(NSObject())) + XCTAssertFalse(falsePredicate.evaluateWithObject(NSObject())) + } + + + func test_BlockPredicateWithoutVariableBindings() { + let isNSStringPredicate = NSPredicate { (object, bindings) -> Bool in + return object is NSString + } + + XCTAssertTrue(isNSStringPredicate.evaluateWithObject(NSString())) + XCTAssertFalse(isNSStringPredicate.evaluateWithObject(NSArray())) + } + + + func test_filterNSArray() { + let predicate = NSPredicate { (obj, bindings) -> Bool in + return (obj as? NSString).map({ $0.length <= 2 }) == true + } + + let array = NSArray(array: ["1".bridge(), "12".bridge(), "123".bridge(), "1234".bridge()]) + let filteredArray = array.filteredArrayUsingPredicate(predicate).bridge() + + XCTAssertEqual(["1".bridge(), "12".bridge()].bridge(), filteredArray) + } +} diff --git a/TestFoundation/main.swift b/TestFoundation/main.swift index fb4571b0bb..4a5604d91b 100644 --- a/TestFoundation/main.swift +++ b/TestFoundation/main.swift @@ -27,6 +27,7 @@ XCTMain([ testCase(TestNSByteCountFormatter.allTests), testCase(TestNSCalendar.allTests), testCase(TestNSCharacterSet.allTests), + testCase(TestNSCompoundPredicate.allTests), testCase(TestNSData.allTests), testCase(TestNSDate.allTests), testCase(TestNSDateFormatter.allTests), @@ -41,11 +42,13 @@ XCTMain([ testCase(TestNSKeyedUnarchiver.allTests), testCase(TestNSLocale.allTests), testCase(TestNSNotificationCenter.allTests), - testCase(TestNSNull.allTests), testCase(TestNSNotificationQueue.allTests), + testCase(TestNSNull.allTests), testCase(TestNSNumber.allTests), testCase(TestNSNumberFormatter.allTests), + testCase(TestNSOrderedSet.allTests), testCase(TestNSPipe.allTests), + testCase(TestNSPredicate.allTests), testCase(TestNSProcessInfo.allTests), testCase(TestNSPropertyList.allTests), testCase(TestNSRange.allTests), @@ -53,7 +56,6 @@ XCTMain([ testCase(TestNSRunLoop.allTests), testCase(TestNSScanner.allTests), testCase(TestNSSet.allTests), - testCase(TestNSOrderedSet.allTests), testCase(TestNSString.allTests), // testCase(TestNSTask.allTests), // testCase(TestNSThread.allTests),