├── .gitignore ├── LICENSE.txt ├── README.md ├── Sources ├── Utils │ ├── CTSBetterTouchToolWebServerConfiguration.h │ ├── CTSBetterTouchToolWebServerConfiguration.m │ ├── CTSService.h │ ├── CTSWeakify.h │ ├── NSDictionary+CTSCommandLineArguments.h │ ├── NSDictionary+CTSCommandLineArguments.m │ ├── NSURL+CTSBetterTouchToolWebServerEndpoint.h │ └── NSURL+CTSBetterTouchToolWebServerEndpoint.m ├── controlstrip-service │ ├── CTSControlStripService.h │ ├── CTSControlStripService.m │ └── main.m ├── eventkit-service │ ├── CTSEventKitService.h │ ├── CTSEventKitService.m │ ├── EKEvent+CTSVisibility.h │ ├── EKEvent+CTSVisibility.m │ ├── NSString+CTSReadableEventStatus.h │ ├── NSString+CTSReadableEventStatus.m │ └── main.m └── volume-service │ ├── CTSVolumeService.h │ ├── CTSVolumeService.m │ ├── NSString+CTSSerializedVolumeStatus.h │ ├── NSString+CTSSerializedVolumeStatus.m │ └── main.m ├── Tests ├── CTSBetterTouchToolWebServerConfigurationTests.m ├── CTSControlStripServiceTests.m ├── CTSEventKitServiceTests.m ├── CTSVolumeServiceTests.m ├── EKEventCTSVisibilityTests.m ├── Frameworks │ ├── OCHamcrest.framework │ │ ├── Headers │ │ ├── Modules │ │ ├── OCHamcrest │ │ ├── Resources │ │ └── Versions │ │ │ ├── A │ │ │ ├── Headers │ │ │ │ ├── HCAllOf.h │ │ │ │ ├── HCAnyOf.h │ │ │ │ ├── HCArgumentCaptor.h │ │ │ │ ├── HCAssertThat.h │ │ │ │ ├── HCBaseDescription.h │ │ │ │ ├── HCBaseMatcher.h │ │ │ │ ├── HCClassMatcher.h │ │ │ │ ├── HCCollect.h │ │ │ │ ├── HCConformsToProtocol.h │ │ │ │ ├── HCDescribedAs.h │ │ │ │ ├── HCDescription.h │ │ │ │ ├── HCDiagnosingMatcher.h │ │ │ │ ├── HCEvery.h │ │ │ │ ├── HCHasCount.h │ │ │ │ ├── HCHasDescription.h │ │ │ │ ├── HCHasProperty.h │ │ │ │ ├── HCInvocationMatcher.h │ │ │ │ ├── HCIs.h │ │ │ │ ├── HCIsAnything.h │ │ │ │ ├── HCIsCloseTo.h │ │ │ │ ├── HCIsCollectionContaining.h │ │ │ │ ├── HCIsCollectionContainingInAnyOrder.h │ │ │ │ ├── HCIsCollectionContainingInOrder.h │ │ │ │ ├── HCIsCollectionContainingInRelativeOrder.h │ │ │ │ ├── HCIsCollectionOnlyContaining.h │ │ │ │ ├── HCIsDictionaryContaining.h │ │ │ │ ├── HCIsDictionaryContainingEntries.h │ │ │ │ ├── HCIsDictionaryContainingKey.h │ │ │ │ ├── HCIsDictionaryContainingValue.h │ │ │ │ ├── HCIsEmptyCollection.h │ │ │ │ ├── HCIsEqual.h │ │ │ │ ├── HCIsEqualCompressingWhiteSpace.h │ │ │ │ ├── HCIsEqualIgnoringCase.h │ │ │ │ ├── HCIsEqualToNumber.h │ │ │ │ ├── HCIsIn.h │ │ │ │ ├── HCIsInstanceOf.h │ │ │ │ ├── HCIsNil.h │ │ │ │ ├── HCIsNot.h │ │ │ │ ├── HCIsSame.h │ │ │ │ ├── HCIsTrueFalse.h │ │ │ │ ├── HCIsTypeOf.h │ │ │ │ ├── HCMatcher.h │ │ │ │ ├── HCNumberAssert.h │ │ │ │ ├── HCOrderingComparison.h │ │ │ │ ├── HCRequireNonNilObject.h │ │ │ │ ├── HCSelfDescribing.h │ │ │ │ ├── HCStringContains.h │ │ │ │ ├── HCStringContainsInOrder.h │ │ │ │ ├── HCStringDescription.h │ │ │ │ ├── HCStringEndsWith.h │ │ │ │ ├── HCStringStartsWith.h │ │ │ │ ├── HCSubstringMatcher.h │ │ │ │ ├── HCTestFailure.h │ │ │ │ ├── HCTestFailureReporter.h │ │ │ │ ├── HCTestFailureReporterChain.h │ │ │ │ ├── HCThrowsException.h │ │ │ │ ├── HCWrapInMatcher.h │ │ │ │ └── OCHamcrest.h │ │ │ ├── Modules │ │ │ │ └── module.modulemap │ │ │ ├── OCHamcrest │ │ │ └── Resources │ │ │ │ └── Info.plist │ │ │ └── Current │ └── OCMockito.framework │ │ ├── Headers │ │ ├── Modules │ │ ├── OCMockito │ │ ├── Resources │ │ └── Versions │ │ ├── A │ │ ├── Headers │ │ │ ├── MKTBaseMockObject.h │ │ │ ├── MKTClassObjectMock.h │ │ │ ├── MKTNonObjectArgumentMatching.h │ │ │ ├── MKTObjectAndProtocolMock.h │ │ │ ├── MKTObjectMock.h │ │ │ ├── MKTOngoingStubbing.h │ │ │ ├── MKTProtocolMock.h │ │ │ ├── NSInvocation+OCMockito.h │ │ │ └── OCMockito.h │ │ ├── Modules │ │ │ └── module.modulemap │ │ ├── OCMockito │ │ └── Resources │ │ │ └── Info.plist │ │ └── Current ├── NSDictionaryCTSCommandLineArgumentsTests.m ├── NSStringCTSReadableEventStatusTests.m ├── NSStringCTSSerializedVolumeStatusTests.m ├── NSURLCTSBetterTouchToolWebServerEndpointTests.m └── Stubs │ ├── CTSAudioToolboxControlStripServiceTestStub.h │ ├── CTSAudioToolboxControlStripServiceTestStub.m │ ├── CTSAudioToolboxVolumeServiceTestStub.h │ ├── CTSAudioToolboxVolumeServiceTestStub.m │ ├── CTSCoreGraphicsEventControlStripServiceTestStub.h │ └── CTSCoreGraphicsEventControlStripServiceTestStub.m └── btt-services.xcodeproj └── project.pbxproj /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | */build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | *.hmap 19 | 20 | # macOS 21 | .DS_Store 22 | 23 | # Files that might appear on external disk 24 | .Spotlight-V100 25 | .Trashes 26 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | btt-services 2 | Copyright © 2018 CarbonTech Software LLC 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | ----- 22 | 23 | OCMockito by Jon Reid, https://qualitycoding.org/ 24 | Copyright 2017 Jonathan M. Reid 25 | 26 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 29 | 30 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | 32 | (MIT License) 33 | 34 | ----- 35 | 36 | TPDWeakProxy: 37 | 38 | The MIT License (MIT) 39 | 40 | Copyright © 2013 Tetherpad 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy of 43 | this software and associated documentation files (the "Software"), to deal in 44 | the Software without restriction, including without limitation the rights to 45 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 46 | the Software, and to permit persons to whom the Software is furnished to do so, 47 | subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in all 50 | copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 54 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 55 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 56 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 57 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | 59 | ----- 60 | 61 | OCHamcrest by Jon Reid, https://qualitycoding.org/ 62 | Copyright 2017 hamcrest.org 63 | All rights reserved. 64 | 65 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 66 | 67 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 68 | 69 | Neither the name of Hamcrest nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 70 | 71 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 72 | 73 | (BSD License) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | btt-services 2 | ============ 3 | 4 | Simple command-line utilities designed for BetterTouchTool presets. Able to use BetterTouchTool’s integrated web server to send low-latency refresh widget messages. 5 | 6 | Most utilities require controller scripts for appearance state and process persistence, which can be found at [andrewchidden/btt-controllers](https://github.com/andrewchidden/btt-controllers). 7 | 8 | Article about the preset at [andrewchidden.com](https://andrewchidden.com/long-live-the-macbook-pro-with-touch-bar/). 9 | 10 | ## EventKit Service 11 | 12 | ### About 13 | 14 | Observes `EventKit` for changes and outputs the upcoming calendar event information in a readable text format. May be extended to read reminders in the future. 15 | 16 | ### API 17 | 18 | ``` 19 | Usage: ./eventkit-service 20 | --lookahead=, -l 21 | How long in minutes to look into the future for events. 22 | 23 | --status-path=, -p 24 | The file path to save the latest event status message. Intermediary directories must exist. 25 | 26 | --empty-message=, -m 27 | The status message to show when there are no events within `lookahead`. If not specified, 28 | a default message will be shown instead when there are no events. 29 | 30 | --btt-url=, -u 31 | The optional base URL to BetterTouchTool's web server in the format `protocol://hostname:port`. 32 | If not specified, the service will not push updates to BetterTouchTool. 33 | 34 | --btt-secret=, -s 35 | The optional shared secret to authenticate with BetterTouchTool's web server. 36 | 37 | --widget-uuid=, -w 38 | The UUID of the BetterTouchTool widget to refresh on update pushes. If not specified, the 39 | service will not push updates to BetterTouchTool. 40 | 41 | --calendars=, -c 42 | An optional comma delimited list of case-sensitive calendar names to check for events. If 43 | not specified, the service checks all calendars for events. 44 | 45 | --delimiter=, -d 46 | The optional string delimiter to use for separating calendar names. If not specified, the 47 | service will use comma for the calendar name list delimiter. 48 | ``` 49 | 50 | ## Volume Service 51 | 52 | ### About 53 | 54 | Listens for volume changes from `CoreAudio` and outputs a serialized device volume state. 55 | 56 | ### API 57 | 58 | ``` 59 | Usage: ./volume-service 60 | --status-path=, -p 61 | The file path to save the latest volume state. Intermediary directories must exist. 62 | 63 | --btt-url=, -u 64 | The optional base URL to BetterTouchTool's web server in the format `protocol://hostname:port`. 65 | If not specified, the service will not push updates to BetterTouchTool. 66 | 67 | --btt-secret=, -s 68 | The optional shared secret to authenticate with BetterTouchTool's web server. 69 | 70 | --widget-uuid=, -w 71 | The UUID of the BetterTouchTool widget to refresh on update pushes. If not specified, the 72 | service will not push updates to BetterTouchTool. 73 | 74 | --use-threshold=, -u 75 | Whether to only treat changes between volume appearance thresholds as valid events. See 76 | also, `--thresholds, -t`. 77 | 78 | --thresholds=, -t 79 | An optional list of comma-delimited, strictly-greater-than thresholds in descending order. 80 | If not specified, [65,32,0] is used instead, corresponding to the system thresholds. 81 | ``` 82 | 83 | ## Control Strip Service 84 | 85 | ### About 86 | 87 | Replicates system-level keyboard buttons (volume, brightness) and additional side effects (feedback sound, open preference pane) based on the current set of modifier keys (shift, option). 88 | 89 | ### API 90 | 91 | ``` 92 | Usage: ./controlstrip-service 93 | --type=, -t 94 | The class of keyboard events to handle. Should be either `volume` or `brightness`. 95 | - `volume` modifier key behavior: 96 | [None] Adjusts volume. 97 | [Shift] Plays feedback sound. 98 | [Option] Opens Volume preference pane in System Preferences. 99 | [Shift+Option] Small volume adjustments. 100 | - `brightness` modifier key behavior: 101 | [None] Adjusts screen brightness. 102 | [Shift] Changes keyboard illumination. 103 | [Option] Opens Displays preference pane in System Preferences. 104 | [Shift+Option] Small screen brightness adjustments. 105 | 106 | --direction=, -d 107 | The direction of the change, either 0 or 1, where 0 is decrement, 1 is increment. 108 | ``` 109 | 110 | ## Building from Source 111 | 112 | 1. Download and install the latest version of [Xcode](https://developer.apple.com/xcode/). 113 | 2. Open `./btt-services.xcodeproj`. 114 | 3. Build each target (for Running = **debug**, for Profiling = **release**). 115 | 116 | ## Contributing 117 | 118 | Contributions welcomed. Some ground rules: 119 | 120 | - Please ensure that you follow the style of the codebase which takes inspiration from [Google’s Objective-C style guide](https://google.github.io/styleguide/objcguide.html). 121 | - Add unit tests for all core service functionality. This project uses [OCMockito](https://github.com/jonreid/OCMockito) for general-purpose mocking and verification. 122 | - To test services that use C-style function APIs, create a stub and forward invocations to a concrete mock. Examples can be found in `./Tests/Stubs`. 123 | - Keep code coverage of services and service utilities above 95%, using the [code coverage feature](https://www.bignerdranch.com/blog/weve-got-you-covered/) in Xcode. 124 | 125 | ## Contact 126 | 127 | ``` 128 | "andrew" 129 | "@" 130 | "andrewchidden.com" 131 | ``` 132 | 133 | ## License 134 | 135 | Copyright © 2018 CarbonTech Software LLC 136 | 137 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 138 | 139 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 140 | 141 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Sources/Utils/CTSBetterTouchToolWebServerConfiguration.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | /** 6 | A @c CTSBetterTouchToolWebServerConfiguration object holds information used to connect to BetterTouchTool's web server. 7 | */ 8 | @interface CTSBetterTouchToolWebServerConfiguration : NSObject 9 | 10 | /// Create a new configuration. 11 | - (instancetype)initWithURL:(NSURL * const)URL sharedSecret:(nullable NSString * const)sharedSecret 12 | NS_DESIGNATED_INITIALIZER; 13 | - (instancetype)init NS_UNAVAILABLE; 14 | 15 | /// The base URL to BetterTouchTool's web server, e.g. `http://127.0.0.1:12345` 16 | @property (nonatomic, strong, readonly) NSURL *URL; 17 | 18 | /// The optional shared secret to authenticate with BetterTouchTool's web server. 19 | @property (nonatomic, strong, readonly, nullable) NSString *sharedSecret; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /Sources/Utils/CTSBetterTouchToolWebServerConfiguration.m: -------------------------------------------------------------------------------- 1 | #import "CTSBetterTouchToolWebServerConfiguration.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @implementation CTSBetterTouchToolWebServerConfiguration 6 | 7 | - (instancetype)initWithURL:(NSURL * const)URL sharedSecret:(nullable NSString * const)sharedSecret 8 | { 9 | self = [super init]; 10 | 11 | if (self) { 12 | _URL = URL; 13 | _sharedSecret = [sharedSecret copy]; 14 | } 15 | 16 | return self; 17 | } 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /Sources/Utils/CTSService.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | Objects that implement @c CTSService should be runnable after initialization. 5 | */ 6 | @protocol CTSService 7 | 8 | /// Whether or not the service is running. If the service encounters an error then @c running will be set to @c NO. 9 | @property (nonatomic, assign, readonly, getter=isRunning) BOOL running; 10 | 11 | /// Start the service, adding observers and setting status as required. 12 | - (void)start; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Sources/Utils/CTSWeakify.h: -------------------------------------------------------------------------------- 1 | /// @see http://holko.pl/2015/05/31/weakify-strongify/ 2 | 3 | #define weakify(var) __weak typeof(var) CTSWeak_##var = var; 4 | 5 | #define strongify(var) \ 6 | _Pragma("clang diagnostic push") \ 7 | _Pragma("clang diagnostic ignored \"-Wshadow\"") \ 8 | __strong typeof(var) var = CTSWeak_##var; \ 9 | _Pragma("clang diagnostic pop") 10 | -------------------------------------------------------------------------------- /Sources/Utils/NSDictionary+CTSCommandLineArguments.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface NSDictionary (CTSCommandLineArguments) 6 | 7 | /** 8 | Convert an array of @c NSString command-line arguments, such as those from @c NSProcessInfo into key-value pairs. 9 | 10 | @note Only supports options in the format `--key=value` and `-k value`. 11 | 12 | @param arguments An array containing the command-line arguments as strings. 13 | @return A dictionary of the command-line arguments as key-value pairs for each option and its value. 14 | */ 15 | + (NSDictionary *)cts_dictionaryWithCommandLineArguments:(NSArray * const)arguments; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Sources/Utils/NSDictionary+CTSCommandLineArguments.m: -------------------------------------------------------------------------------- 1 | #import "NSDictionary+CTSCommandLineArguments.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @implementation NSDictionary (CTSCommandLineArguments) 6 | 7 | + (NSDictionary *)cts_dictionaryWithCommandLineArguments:(NSArray * const)arguments 8 | { 9 | NSMutableDictionary * const argumentsDictionary = [NSMutableDictionary dictionary]; 10 | 11 | for (NSInteger index = 1; index < arguments.count; index++) { 12 | NSString * const argument = arguments[index]; 13 | if ([argument rangeOfString:@"--"].location != NSNotFound && 14 | [argument rangeOfString:@"="].location != NSNotFound) { // `--key=value` 15 | NSArray * const components = [argument componentsSeparatedByString:@"="]; 16 | NSString * const key = 17 | [[components objectAtIndex:0] stringByReplacingOccurrencesOfString:@"--" withString:@""]; 18 | NSIndexSet * const indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, components.count-1)]; 19 | NSString * const value = [[components objectsAtIndexes:indexSet] componentsJoinedByString:@"="]; 20 | 21 | argumentsDictionary[key] = value; 22 | } else if ([argument rangeOfString:@"-"].location == 0) { // `-k value` 23 | NSString * const key = [argument stringByReplacingOccurrencesOfString:@"-" withString:@""]; 24 | NSString * const value = [arguments objectAtIndex:(index + 1)]; 25 | 26 | argumentsDictionary[key] = value; 27 | } 28 | } 29 | 30 | return argumentsDictionary; 31 | } 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END 36 | -------------------------------------------------------------------------------- /Sources/Utils/NSURL+CTSBetterTouchToolWebServerEndpoint.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class CTSBetterTouchToolWebServerConfiguration; 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface NSURL (CTSBetterTouchToolWebServerEndpoint) 8 | 9 | /** 10 | Create a BetterTouchTool web server URL. 11 | 12 | @param webServerConfiguration A BetterTouchTool web server configuration object. 13 | @param endpoint A path to the BetterTouchTool web server endpoint. 14 | @param queryParameters An optional array of GET query parameters in the form `key=value`. 15 | @return A new @c NSURL instance. 16 | */ 17 | + (NSURL *)cts_URLWithWebServerConfiguration:(CTSBetterTouchToolWebServerConfiguration * const)webServerConfiguration 18 | endpoint:(NSString * const)endpoint 19 | queryParameters:(nullable NSArray * const)queryParameters; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /Sources/Utils/NSURL+CTSBetterTouchToolWebServerEndpoint.m: -------------------------------------------------------------------------------- 1 | #import "NSURL+CTSBetterTouchToolWebServerEndpoint.h" 2 | #import "CTSBetterTouchToolWebServerConfiguration.h" 3 | 4 | static NSString * const kSharedSecretQueryParameterKey = @"shared_secret"; 5 | 6 | NS_ASSUME_NONNULL_BEGIN 7 | 8 | @implementation NSURL (CTSBetterTouchToolWebServerEndpoint) 9 | 10 | + (NSURL *)cts_URLWithWebServerConfiguration:(CTSBetterTouchToolWebServerConfiguration * const)webServerConfiguration 11 | endpoint:(NSString * const)endpoint 12 | queryParameters:(nullable NSArray * const)queryParameters 13 | { 14 | NSString *URLString = [webServerConfiguration.URL URLByAppendingPathComponent:endpoint].absoluteString; 15 | if (![URLString hasSuffix:@"/"]) { // DRAGON: BetterTouchTool requires endpoints to be at the directory level. 16 | URLString = [URLString stringByAppendingString:@"/"]; 17 | } 18 | NSURLComponents * const components = [NSURLComponents componentsWithString:URLString]; 19 | NSMutableArray * const decoratedQueryParameters = [(queryParameters ?: @[]) mutableCopy]; 20 | if (webServerConfiguration.sharedSecret) { 21 | [decoratedQueryParameters addObject:[NSString stringWithFormat:@"%@=%@", 22 | kSharedSecretQueryParameterKey, webServerConfiguration.sharedSecret]]; 23 | } 24 | NSString * const queryParameterString = [(decoratedQueryParameters ?: @[]) componentsJoinedByString:@"&"]; 25 | components.query = queryParameterString; 26 | return components.URL; 27 | } 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /Sources/controlstrip-service/CTSControlStripService.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "CTSService.h" 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | /// The type control action to perform. 8 | typedef NS_ENUM(NSUInteger, CTSControlStripControlType) 9 | { 10 | CTSControlStripNoControl = 0, 11 | 12 | CTSControlStripVolumeUpControl = 1, 13 | CTSControlStripVolumeDownControl, 14 | 15 | CTSControlStripBrightnessUpControl = 101, 16 | CTSControlStripBrightnessDownControl, 17 | }; 18 | 19 | @interface CTSControlStripService : NSObject 20 | 21 | /** 22 | Create a service. 23 | 24 | @param controlType The type of control action to perform. 25 | @param modifierFlags The current set of keyed-down modifier flags. 26 | @param workspace The workspace object to use for opening preference panes in System Preferences. 27 | @return A new control strip service instance. 28 | */ 29 | - (instancetype)initWithControlType:(CTSControlStripControlType)controlType 30 | modifierFlags:(NSEventModifierFlags)modifierFlags 31 | workspace:(NSWorkspace *)workspace NS_DESIGNATED_INITIALIZER; 32 | - (instancetype)init NS_UNAVAILABLE; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /Sources/controlstrip-service/CTSControlStripService.m: -------------------------------------------------------------------------------- 1 | #import "CTSControlStripService.h" 2 | #import 3 | #import 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface CTSControlStripService () 8 | 9 | @property (nonatomic, assign, readonly) CTSControlStripControlType controlType; 10 | @property (nonatomic, strong, readonly) NSWorkspace *workspace; 11 | @property (nonatomic, assign, readonly, getter=isShiftPressed) BOOL shiftPressed; 12 | @property (nonatomic, assign, readonly, getter=isOptionPressed) BOOL optionPressed; 13 | @property (nonatomic, assign, readonly) BOOL shouldPerformModifiedKeyPress; 14 | @property (nonatomic, assign, readonly, getter=isVolumeControlType) BOOL volumeControlType; 15 | @property (nonatomic, assign, readonly) CGKeyCode keyCode; 16 | @property (nonatomic, assign, readwrite) io_connect_t hidConnection; 17 | 18 | @end 19 | 20 | @implementation CTSControlStripService 21 | 22 | @synthesize running = _running; 23 | 24 | - (instancetype)initWithControlType:(CTSControlStripControlType)controlType 25 | modifierFlags:(NSEventModifierFlags)modifierFlags 26 | workspace:(NSWorkspace *)workspace 27 | { 28 | self = [super init]; 29 | 30 | if (self) { 31 | _controlType = controlType; 32 | _workspace = workspace; 33 | _volumeControlType = controlType == CTSControlStripVolumeUpControl 34 | || controlType == CTSControlStripVolumeDownControl; 35 | 36 | _shiftPressed = !!(modifierFlags & NSEventModifierFlagShift); 37 | _optionPressed = !!(modifierFlags & NSEventModifierFlagOption); 38 | 39 | CGKeyCode code = 0; 40 | if (_volumeControlType) { 41 | code = (controlType == CTSControlStripVolumeUpControl ? NX_KEYTYPE_SOUND_UP : NX_KEYTYPE_SOUND_DOWN); 42 | } else { 43 | if (_shiftPressed && !_optionPressed) { 44 | code = (controlType == CTSControlStripBrightnessUpControl ? NX_KEYTYPE_ILLUMINATION_UP 45 | : NX_KEYTYPE_ILLUMINATION_DOWN); 46 | _shouldPerformModifiedKeyPress = YES; 47 | } else { 48 | code = (controlType == CTSControlStripBrightnessUpControl ? NX_KEYTYPE_BRIGHTNESS_UP 49 | : NX_KEYTYPE_BRIGHTNESS_DOWN); 50 | } 51 | } 52 | _keyCode = code; 53 | 54 | mach_port_t masterPort; 55 | io_service_t service = 0; 56 | kern_return_t returnValue; 57 | 58 | returnValue = IOMasterPort(bootstrap_port, &masterPort); 59 | if (returnValue != KERN_SUCCESS) { 60 | return nil; 61 | } 62 | 63 | service = IOServiceGetMatchingService(masterPort, IOServiceMatching(kIOHIDSystemClass)); 64 | if (service == 0) { 65 | return nil; 66 | } 67 | 68 | returnValue = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &_hidConnection); 69 | if (returnValue != KERN_SUCCESS) { 70 | return nil; 71 | } 72 | } 73 | 74 | return self; 75 | } 76 | 77 | - (void)start 78 | { 79 | _running = YES; 80 | if (self.shouldPerformModifiedKeyPress) { 81 | [self performModifiedKeyPress]; 82 | } else { 83 | [self performKeyPress]; 84 | } 85 | _running = NO; 86 | } 87 | 88 | - (void)performKeyPress 89 | { 90 | NXEventData event = {0}; 91 | IOGPoint point = {0}; 92 | kern_return_t returnValue; 93 | 94 | event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; 95 | event.compound.misc.L[0] = (NX_KEYDOWN << 8) | (self.keyCode << 16); 96 | returnValue = IOHIDPostEvent(self.hidConnection, 97 | NX_SYSDEFINED, 98 | point, 99 | &event, 100 | kNXEventDataVersion, 101 | 0, 102 | 0); 103 | if (returnValue != KERN_SUCCESS) { 104 | return; 105 | } 106 | 107 | event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; 108 | event.compound.misc.L[0] = (NX_KEYUP << 8) | (self.keyCode << 16); 109 | returnValue = IOHIDPostEvent(self.hidConnection, 110 | NX_SYSDEFINED, 111 | point, 112 | &event, 113 | kNXEventDataVersion, 114 | 0, 115 | 0); 116 | if (returnValue != KERN_SUCCESS) { 117 | return; 118 | } 119 | } 120 | 121 | - (void)performModifiedKeyPress 122 | { 123 | NSEvent * const keyDownEvent = [NSEvent otherEventWithType:NSEventTypeSystemDefined 124 | location:NSPointFromCGPoint(CGPointZero) 125 | modifierFlags:NX_KEYDOWN 126 | timestamp:0 127 | windowNumber:0 128 | context:nil 129 | subtype:8 130 | data1:((self.keyCode << 16) | (NX_KEYDOWN << 8)) 131 | data2:-1]; 132 | CGEventPost(kCGHIDEventTap, [keyDownEvent CGEvent]); 133 | 134 | usleep(1000); // DRAGON: Not waiting can cause the key press to execute out-of-order and fail. 135 | 136 | NSEvent * const keyUpEvent = [NSEvent otherEventWithType:NSEventTypeSystemDefined 137 | location:NSPointFromCGPoint(CGPointZero) 138 | modifierFlags:NX_KEYUP 139 | timestamp:0 140 | windowNumber:0 141 | context:nil 142 | subtype:8 143 | data1:((self.keyCode << 16) | (NX_KEYUP << 8)) 144 | data2:-1]; 145 | CGEventPost(kCGHIDEventTap, [keyUpEvent CGEvent]); 146 | 147 | usleep(15000); 148 | } 149 | 150 | @end 151 | 152 | NS_ASSUME_NONNULL_END 153 | -------------------------------------------------------------------------------- /Sources/controlstrip-service/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "NSDictionary+CTSCommandLineArguments.h" 4 | #import "CTSControlStripService.h" 5 | 6 | static NSString * const kCalendarNameDefaultDelimiter = @","; 7 | 8 | int main(int argc, const char * argv[]) { 9 | @autoreleasepool { 10 | NSDictionary * const dictionary = 11 | [NSDictionary cts_dictionaryWithCommandLineArguments:[NSProcessInfo processInfo].arguments]; 12 | NSString * _Nullable const typeString = dictionary[@"type"] ?: dictionary[@"t"]; 13 | NSString * _Nullable const directionString = dictionary[@"direction"] ?: dictionary[@"d"]; 14 | 15 | if (!typeString || 16 | !directionString) { 17 | fputs("Usage: ./controlstrip-service\n" 18 | " --type=, -t \n" 19 | " The class of keyboard events to handle. Should be either `volume` or `brightness`.\n" 20 | " - `volume` modifier key behavior:\n" 21 | " [None] Adjusts volume.\n" 22 | " [Shift] Plays feedback sound.\n" 23 | " [Option] Opens Volume preference pane in System Preferences.\n" 24 | " [Shift+Option] Small volume adjustments.\n" 25 | " - `brightness` modifier key behavior:\n" 26 | " [None] Adjusts screen brightness.\n" 27 | " [Shift] Changes keyboard illumination.\n" 28 | " [Option] Opens Displays preference pane in System Preferences.\n" 29 | " [Shift+Option] Small screen brightness adjustments.\n\n" 30 | 31 | " --direction=, -d \n" 32 | " The direction of the change, either 0 or 1, where 0 is decrement, 1 is increment.\n\n", 33 | stderr); 34 | return 1; 35 | } 36 | 37 | BOOL const isVolumeType = [typeString isEqualToString:@"volume"]; 38 | BOOL const shouldIncrement = directionString.boolValue; 39 | 40 | CTSControlStripControlType type; 41 | if (isVolumeType) { 42 | type = (shouldIncrement ? CTSControlStripVolumeUpControl : CTSControlStripVolumeDownControl); 43 | } else { 44 | type = (shouldIncrement ? CTSControlStripBrightnessUpControl : CTSControlStripBrightnessDownControl); 45 | } 46 | 47 | NSEventModifierFlags const modifierFlags = [NSEvent modifierFlags]; 48 | NSWorkspace * const workspace = [NSWorkspace sharedWorkspace]; 49 | CTSControlStripService * const service = 50 | [[CTSControlStripService alloc] initWithControlType:type 51 | modifierFlags:modifierFlags 52 | workspace:workspace]; 53 | [service start]; 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Sources/eventkit-service/CTSEventKitService.h: -------------------------------------------------------------------------------- 1 | #import "CTSService.h" 2 | 3 | @class EKEventStore; 4 | @class CTSBetterTouchToolWebServerConfiguration; 5 | 6 | NS_ASSUME_NONNULL_BEGIN 7 | 8 | /** 9 | A @c CTSEventKitService object can receive event store change notifications and push an update to BTT's webserver. 10 | */ 11 | @interface CTSEventKitService : NSObject 12 | 13 | /** 14 | Create a service. 15 | 16 | @param eventStore The EventKit store used to fetch calendar events and receive update notifications. 17 | @param notificationCenter The notification center to use for subscribing to calendar event change notifications. 18 | @param URLSession The URL session to use when pushing requests to BetterTouchTool. 19 | @param runLoop The run loop used to add and run the update event message timer. 20 | @param eventLookahead How long to look into the future for events. 21 | @param statusFilePath The file path to save the latest event status message. Intermediary directories must exist. 22 | @param noEventsMessage The optional status message to display when there are no events within @c eventLookahead. If 23 | nil, a default no events message will be shown instead. 24 | @param calendarNames An optional list of case-sensitive calendar names to check. If nil, all calendars are checked. 25 | @param widgetUUID An optional widget UUID to push refresh updates after an event changes. If nil, no pushes occur. 26 | @param webServerConfiguration The optional BetterTouchTool web server configuration object. If nil, no pushes occur. 27 | @return A new EventKit service instance. 28 | */ 29 | - (instancetype)initWithEventStore:(EKEventStore * const)eventStore 30 | notificationCenter:(NSNotificationCenter * const)notificationCenter 31 | URLSession:(NSURLSession * const)URLSession 32 | runLoop:(NSRunLoop * const)runLoop 33 | eventLookahead:(NSTimeInterval const)eventLookahead 34 | statusFilePath:(NSString * const)statusFilePath 35 | noEventsMessage:(nullable NSString * const)noEventsMessage 36 | calendarNames:(nullable NSArray * const)calendarNames 37 | widgetUUID:(nullable NSString * const)widgetUUID 38 | webServerConfiguration:(nullable CTSBetterTouchToolWebServerConfiguration * const)webServerConfiguration 39 | NS_DESIGNATED_INITIALIZER; 40 | - (instancetype)init NS_UNAVAILABLE; 41 | 42 | @end 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /Sources/eventkit-service/CTSEventKitService.m: -------------------------------------------------------------------------------- 1 | #import "CTSEventKitService.h" 2 | 3 | #import 4 | 5 | #import "CTSWeakify.h" 6 | 7 | #import "EKEvent+CTSVisibility.h" 8 | #import "NSString+CTSReadableEventStatus.h" 9 | #import "NSURL+CTSBetterTouchToolWebServerEndpoint.h" 10 | 11 | #import "CTSBetterTouchToolWebServerConfiguration.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | static NSTimeInterval const kUpdateEventMessageTimerInterval = 15.0; 16 | static NSString * const kNoEventsDefaultStatusMessage = @"No upcoming meetings"; 17 | static NSString * const kBetterTouchToolRefreshWidgetEndpoint = @"refresh_widget"; 18 | 19 | @interface CTSEventKitService () 20 | 21 | @property (nonatomic, strong, readonly) EKEventStore *eventStore; 22 | @property (nonatomic, strong, readonly) NSNotificationCenter *notificationCenter; 23 | @property (nonatomic, strong, readonly) NSURLSession *URLSession; 24 | @property (nonatomic, strong, readonly) NSRunLoop *runLoop; 25 | @property (nonatomic, assign, readonly) NSTimeInterval eventLookahead; 26 | @property (nonatomic, strong, readonly) NSString *statusFilePath; 27 | @property (nonatomic, strong, readonly) NSString *noEventsMessage; 28 | @property (nonatomic, strong, readonly, nullable) NSString *widgetUUID; 29 | @property (nonatomic, strong, readonly, nullable) CTSBetterTouchToolWebServerConfiguration *webServerConfiguration; 30 | @property (nonatomic, strong, readwrite) NSArray *calendars; 31 | @property (nonatomic, strong, readonly) NSArray *calendarNames; 32 | @property (nonatomic, strong, readonly) NSTimer *updateTimer; 33 | 34 | @property (nonatomic, strong, readwrite, nullable) EKEvent *nextEvent; 35 | @property (nonatomic, assign, readwrite) CFAbsoluteTime lastStatusSaveTime; 36 | @property (nonatomic, strong, readwrite, nullable) NSString *lastSavedStatus; 37 | 38 | @end 39 | 40 | @implementation CTSEventKitService 41 | 42 | @synthesize running = _running; 43 | 44 | - (instancetype)initWithEventStore:(EKEventStore * const)eventStore 45 | notificationCenter:(NSNotificationCenter * const)notificationCenter 46 | URLSession:(NSURLSession * const)URLSession 47 | runLoop:(NSRunLoop * const)runLoop 48 | eventLookahead:(NSTimeInterval const)eventLookahead 49 | statusFilePath:(NSString * const)statusFilePath 50 | noEventsMessage:(nullable NSString * const)noEventsMessage 51 | calendarNames:(nullable NSArray * const)calendarNames 52 | widgetUUID:(nullable NSString * const)widgetUUID 53 | webServerConfiguration:(nullable CTSBetterTouchToolWebServerConfiguration * const)webServerConfiguration 54 | { 55 | self = [super init]; 56 | 57 | if (self) { 58 | _eventStore = eventStore; 59 | _notificationCenter = notificationCenter; 60 | _URLSession = URLSession; 61 | _eventLookahead = eventLookahead; 62 | _statusFilePath = [statusFilePath copy]; 63 | _noEventsMessage = [noEventsMessage copy] ?: kNoEventsDefaultStatusMessage; 64 | _calendarNames = [calendarNames copy] ?: @[]; 65 | _widgetUUID = [widgetUUID copy]; 66 | _webServerConfiguration = webServerConfiguration; 67 | _runLoop = runLoop; 68 | 69 | weakify(self); 70 | strongify(self); 71 | _updateTimer = [NSTimer timerWithTimeInterval:kUpdateEventMessageTimerInterval 72 | target:self 73 | selector:@selector(saveNextEventToStatusFile) 74 | userInfo:nil 75 | repeats:YES]; 76 | } 77 | 78 | return self; 79 | } 80 | 81 | - (void)start 82 | { 83 | _running = YES; 84 | weakify(self); 85 | [self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL const granted, NSError * const error) { 86 | strongify(self); 87 | if (!granted || error) { 88 | #if DEBUG 89 | NSLog(@"No calendar access, granted: %d, error: %@", granted, error); 90 | #endif 91 | self->_running = NO; 92 | return; 93 | } 94 | 95 | [self setUpService]; 96 | }]; 97 | } 98 | 99 | /// Set up done after receiving calendar access permissions. 100 | - (void)setUpService 101 | { 102 | [self.runLoop addTimer:self.updateTimer forMode:NSRunLoopCommonModes]; 103 | 104 | self.calendars = [self fetchCalendarsWithNames:self.calendarNames]; 105 | [self addCalendarObserver]; 106 | 107 | // Immediately update status file with latest event information. 108 | [self updateNextEvent]; 109 | } 110 | 111 | 112 | #pragma mark - EventKit notification handling 113 | 114 | - (void)addCalendarObserver 115 | { 116 | [self.notificationCenter addObserver:self 117 | selector:@selector(eventStoreChanged:) 118 | name:EKEventStoreChangedNotification 119 | object:self.eventStore]; 120 | } 121 | 122 | - (void)eventStoreChanged:(NSNotification * const)notification 123 | { 124 | #if DEBUG 125 | NSLog(@"Handling event store change"); 126 | #endif 127 | [self updateNextEvent]; 128 | } 129 | 130 | - (void)updateNextEvent 131 | { 132 | self.nextEvent = [self fetchNextEvent]; 133 | [self saveNextEventToStatusFile]; 134 | } 135 | 136 | 137 | #pragma mark - Update and notify BTT 138 | 139 | - (void)saveNextEventToStatusFile 140 | { 141 | if (self.nextEvent) { 142 | BOOL const hasEventEnded = ([[NSDate date] compare:self.nextEvent.endDate] == NSOrderedDescending); 143 | if (hasEventEnded) { 144 | self.nextEvent = nil; 145 | } 146 | } 147 | 148 | NSString *status = (self.nextEvent ? [NSString cts_stringStatusWithEvent:self.nextEvent referenceDate:[NSDate date]] 149 | : self.noEventsMessage); 150 | if ([status isEqualToString:self.lastSavedStatus]) { 151 | return; 152 | } 153 | 154 | NSError *error = nil; 155 | [status writeToFile:self.statusFilePath atomically:YES encoding:NSUTF8StringEncoding error:&error]; 156 | if (!error) { 157 | self.lastSavedStatus = status; 158 | self.lastStatusSaveTime = CFAbsoluteTimeGetCurrent(); 159 | } 160 | 161 | #if DEBUG 162 | NSLog(@"Saved status to status file, status: %@, file path: %@, error: %@", status, self.statusFilePath, error); 163 | #endif 164 | 165 | [self pushUpdateToWidget]; 166 | } 167 | 168 | - (void)pushUpdateToWidget 169 | { 170 | if (!self.webServerConfiguration || !self.widgetUUID) { 171 | return; 172 | } 173 | 174 | NSURL * const URL = [NSURL cts_URLWithWebServerConfiguration:self.webServerConfiguration 175 | endpoint:kBetterTouchToolRefreshWidgetEndpoint 176 | queryParameters:@[[NSString stringWithFormat:@"uuid=%@",self.widgetUUID]]]; 177 | NSURLRequest * const request = [NSURLRequest requestWithURL:URL 178 | cachePolicy:NSURLRequestReloadIgnoringCacheData 179 | timeoutInterval:1.0]; 180 | NSURLSessionTask * const task = [self.URLSession dataTaskWithRequest:request]; 181 | [task resume]; 182 | 183 | #if DEBUG 184 | NSLog(@"Pushed update to BTT web server at URL: %@", URL); 185 | #endif 186 | } 187 | 188 | 189 | #pragma mark - EventKit utils 190 | 191 | - (NSArray *)fetchCalendarsWithNames:(NSArray * const)calendarNames 192 | { 193 | NSArray * const calendarArray = [self.eventStore calendarsForEntityType:EKEntityTypeEvent]; 194 | NSMutableArray * const filteredArray = [NSMutableArray arrayWithCapacity:calendarArray.count]; 195 | for (EKCalendar * const calendar in calendarArray) { 196 | if ([calendarNames containsObject:calendar.title]) { 197 | [filteredArray addObject:calendar]; 198 | } 199 | } 200 | return filteredArray; 201 | } 202 | 203 | - (nullable EKEvent *)fetchNextEvent 204 | { 205 | NSDate * const endDate = [NSDate dateWithTimeIntervalSinceNow:self.eventLookahead]; 206 | NSPredicate * const predicate = [self.eventStore predicateForEventsWithStartDate:[NSDate date] 207 | endDate:endDate 208 | calendars:self.calendars]; 209 | NSMutableArray * const eventsArray = [NSMutableArray array]; 210 | [self.eventStore enumerateEventsMatchingPredicate:predicate usingBlock:^(EKEvent * const event, BOOL *stop) { 211 | if (event.isVisible && !event.isAllDay) { 212 | [eventsArray addObject:event]; 213 | } 214 | }]; 215 | 216 | EKEvent * const firstEvent = 217 | [eventsArray sortedArrayUsingSelector:@selector(compareStartDateWithEvent:)].firstObject; 218 | return firstEvent; 219 | } 220 | 221 | @end 222 | 223 | NS_ASSUME_NONNULL_END 224 | -------------------------------------------------------------------------------- /Sources/eventkit-service/EKEvent+CTSVisibility.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface EKEvent (CTSVisibility) 6 | 7 | /// Whether or not the event should be visible on the calendar. 8 | @property (nonatomic, assign, readonly, getter=isVisible) BOOL visible; 9 | 10 | @end 11 | 12 | NS_ASSUME_NONNULL_END 13 | -------------------------------------------------------------------------------- /Sources/eventkit-service/EKEvent+CTSVisibility.m: -------------------------------------------------------------------------------- 1 | #import "EKEvent+CTSVisibility.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @implementation EKEvent (CTSVisibility) 6 | 7 | - (BOOL)isVisible 8 | { 9 | BOOL const isConfirmed = self.availability != EKEventAvailabilityFree 10 | || self.availability == EKEventAvailabilityNotSupported; 11 | BOOL const isValid = (self.status != EKEventStatusCanceled); // See docs on `status`. 12 | return (isConfirmed && isValid); 13 | } 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Sources/eventkit-service/NSString+CTSReadableEventStatus.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class EKEvent; 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface NSString (CTSReadableEventStatus) 8 | 9 | /** 10 | Create a readable string that rounds time intervals in a smart manner. 11 | 12 | @param timeInterval The time interval to convert to a readable string. 13 | @return A readable representation of the time interval, rounded to the nearest tenth: 1.25 -> "1.3"; 1.0 -> "1". 14 | */ 15 | + (NSString *)cts_stringWithTimeInterval:(NSTimeInterval const)timeInterval; 16 | 17 | /** 18 | Create a full string status message from an event, based on 19 | 20 | @param event The event to use for start and end dates. 21 | @param referenceDate The date to use to use as the reference point to create the relative times. 22 | @return A string status in the format "{event_title} in {readable_time}" or "{event_title} ending in {readable_time}". 23 | */ 24 | + (NSString *)cts_stringStatusWithEvent:(EKEvent * const)event referenceDate:(NSDate * const)referenceDate; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /Sources/eventkit-service/NSString+CTSReadableEventStatus.m: -------------------------------------------------------------------------------- 1 | #import "NSString+CTSReadableEventStatus.h" 2 | #import 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | @implementation NSString (CTSReadableEventStatus) 7 | 8 | + (NSString *)cts_stringWithRoundedTimeInterval:(NSTimeInterval const)timeInterval units:(NSString * const)units 9 | { 10 | NSString *readableInterval = nil; 11 | if (fmod(timeInterval, 1.0) == 0) { 12 | readableInterval = [NSString stringWithFormat:@"%d %@", (int)(timeInterval), units]; 13 | } else { 14 | readableInterval = [NSString stringWithFormat:@"%.1f %@", timeInterval, units]; 15 | } 16 | if (fabs(timeInterval) != 1) { 17 | readableInterval = [readableInterval stringByAppendingString:@"s"]; 18 | } 19 | return readableInterval; 20 | } 21 | 22 | + (NSString *)cts_stringWithTimeInterval:(NSTimeInterval const)timeInterval 23 | { 24 | if (round(fabs(timeInterval) / 60.0) < 60.0) { 25 | NSTimeInterval minutes = round(timeInterval / 60.0); 26 | return [NSString cts_stringWithRoundedTimeInterval:minutes units:@"min"]; 27 | } else { 28 | NSTimeInterval hours = round(timeInterval / 60.0 / 60.0 * 10.0) / 10.0; 29 | return [NSString cts_stringWithRoundedTimeInterval:hours units:@"hr"]; 30 | } 31 | } 32 | 33 | + (NSString *)cts_stringStatusWithEvent:(EKEvent * const)event referenceDate:(NSDate * const)referenceDate 34 | { 35 | BOOL const hasEventStarted = ([referenceDate compare:event.startDate] == NSOrderedDescending || NSOrderedSame); 36 | NSString * const trimmedTitle = 37 | [event.title stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 38 | 39 | NSString *formattedOutput = nil; 40 | if (hasEventStarted) { 41 | NSString * const readableInterval = 42 | [NSString cts_stringWithTimeInterval:MAX(0, [event.endDate timeIntervalSinceDate:referenceDate])]; 43 | formattedOutput = [NSString stringWithFormat:@"%@ ending in %@", trimmedTitle, readableInterval]; 44 | } else { 45 | NSString * const readableInterval = 46 | [NSString cts_stringWithTimeInterval:MAX(0, [event.startDate timeIntervalSinceDate:referenceDate])]; 47 | formattedOutput = [NSString stringWithFormat:@"%@ in %@", trimmedTitle, readableInterval]; 48 | } 49 | return formattedOutput; 50 | } 51 | 52 | @end 53 | 54 | NS_ASSUME_NONNULL_END 55 | -------------------------------------------------------------------------------- /Sources/eventkit-service/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "NSDictionary+CTSCommandLineArguments.h" 5 | 6 | #import "CTSBetterTouchToolWebServerConfiguration.h" 7 | #import "CTSEventKitService.h" 8 | 9 | static NSString * const kCalendarNameDefaultDelimiter = @","; 10 | 11 | int main(int argc, const char * argv[]) { 12 | @autoreleasepool { 13 | NSDictionary * const dictionary = 14 | [NSDictionary cts_dictionaryWithCommandLineArguments:[NSProcessInfo processInfo].arguments]; 15 | NSString * _Nullable const eventLookahead = dictionary[@"lookahead"] ?: dictionary[@"l"]; 16 | NSString * _Nullable const statusFilePath = dictionary[@"status-path"] ?: dictionary[@"p"]; 17 | NSString * _Nullable const noEventsMessage = dictionary[@"empty-message"] ?: dictionary[@"m"]; 18 | NSString * _Nullable const webServerURLString = dictionary[@"btt-url"] ?: dictionary[@"u"]; 19 | NSString * _Nullable const webServerSharedSecret = dictionary[@"btt-secret"] ?: dictionary[@"s"]; 20 | NSString * _Nullable const widgetUUID = dictionary[@"widget-uuid"] ?: dictionary[@"w"]; 21 | NSString * _Nullable const calendarNamesString = dictionary[@"calendars"] ?: dictionary[@"c"]; 22 | NSString * _Nullable const calendarNameDelimiter = dictionary[@"delimiter"] ?: dictionary[@"d"]; 23 | 24 | if (!statusFilePath || 25 | !eventLookahead || 26 | (widgetUUID && !webServerURLString)) { 27 | fputs("Usage: ./eventkit-service\n" 28 | " --lookahead=, -l \n" 29 | " How long in minutes to look into the future for events.\n\n" 30 | 31 | " --status-path=, -p \n" 32 | " The file path to save the latest event status message. Intermediary directories must exist.\n\n" 33 | 34 | " --empty-message=, -m \n" 35 | " The status message to show when there are no events within `lookahead`. If not specified,\n" 36 | " a default message will be shown instead when there are no events.\n\n" 37 | 38 | " --btt-url=, -u \n" 39 | " The optional base URL to BetterTouchTool's web server in the format `protocol://hostname:port`.\n" 40 | " If not specified, the service will not push updates to BetterTouchTool.\n\n" 41 | 42 | " --btt-secret=, -s \n" 43 | " The optional shared secret to authenticate with BetterTouchTool's web server.\n\n" 44 | 45 | " --widget-uuid=, -w \n" 46 | " The UUID of the BetterTouchTool widget to refresh on update pushes. If not specified, the\n" 47 | " service will not push updates to BetterTouchTool.\n\n" 48 | 49 | " --calendars=, -c \n" 50 | " An optional comma delimited list of case-sensitive calendar names to check for events. If\n" 51 | " not specified, the service checks all calendars for events.\n\n" 52 | 53 | " --delimiter=, -d \n" 54 | " The optional string delimiter to use for separating calendar names. If not specified, the\n" 55 | " service will use comma for the calendar name list delimiter.\n\n", stderr); 56 | return 1; 57 | } 58 | 59 | NSURL * const webServerURL = [NSURL URLWithString:webServerURLString]; 60 | CTSBetterTouchToolWebServerConfiguration * const configuration = 61 | [[CTSBetterTouchToolWebServerConfiguration alloc] initWithURL:webServerURL 62 | sharedSecret:webServerSharedSecret]; 63 | 64 | NSTimeInterval const eventLookaheadSeconds = eventLookahead.integerValue * 60.0; 65 | NSString * const nameDelimiter = calendarNameDelimiter ?: kCalendarNameDefaultDelimiter; 66 | NSArray * const calendarNames = [calendarNamesString componentsSeparatedByString:nameDelimiter]; 67 | 68 | EKEventStore * const eventStore = [[EKEventStore alloc] init]; 69 | NSNotificationCenter * const notificationCenter = [NSNotificationCenter defaultCenter]; 70 | NSURLSession * const URLSession = [NSURLSession sharedSession]; 71 | NSRunLoop * const runLoop = [NSRunLoop currentRunLoop]; 72 | CTSEventKitService * const service = [[CTSEventKitService alloc] initWithEventStore:eventStore 73 | notificationCenter:notificationCenter 74 | URLSession:URLSession 75 | runLoop:runLoop 76 | eventLookahead:eventLookaheadSeconds 77 | statusFilePath:statusFilePath 78 | noEventsMessage:noEventsMessage 79 | calendarNames:calendarNames 80 | widgetUUID:widgetUUID 81 | webServerConfiguration:configuration]; 82 | [service start]; 83 | 84 | [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 85 | while (service.isRunning) { 86 | [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 87 | } 88 | } 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /Sources/volume-service/CTSVolumeService.h: -------------------------------------------------------------------------------- 1 | #import "CTSService.h" 2 | 3 | @class CTSBetterTouchToolWebServerConfiguration; 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface CTSVolumeService : NSObject 8 | 9 | /** 10 | Create a service. 11 | 12 | @param statusFilePath The file path to save the latest event status message. Intermediary directories must exist. 13 | @param URLSession The URL session to use when pushing requests to BetterTouchTool. 14 | @param widgetUUID An optional widget UUID to push refresh updates after an event changes. If nil, no pushes occur. 15 | @param webServerConfiguration The optional BetterTouchTool web server configuration object. If nil, no pushes occur. 16 | @param volumeThresholds An optional set of volume thresholds to check when handling change events. If nil or empty, all 17 | volume change events are handled and pushed to BetterTouchTool. 18 | @return A new volume service instance. 19 | */ 20 | - (instancetype)initWithStatusFilePath:(NSString * const)statusFilePath 21 | URLSession:(NSURLSession * const)URLSession 22 | widgetUUID:(nullable NSString * const)widgetUUID 23 | webServerConfiguration:(nullable CTSBetterTouchToolWebServerConfiguration * const)webServerConfiguration 24 | volumeThresholds:(nullable NSArray * const)volumeThresholds 25 | NS_DESIGNATED_INITIALIZER; 26 | - (instancetype)init NS_UNAVAILABLE; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | -------------------------------------------------------------------------------- /Sources/volume-service/NSString+CTSSerializedVolumeStatus.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface NSString (CTSSerializedVolumeStatus) 6 | 7 | /** 8 | Create a serialized volume string. 9 | 10 | @param volume The volume to serialize, from 0 to 100 inclusive. 11 | @param muteState Whether or not the output volume is muted. 12 | @return A positive integer (between 0 and 100 inclusive) as a string if not muted, or negative if muted. 13 | */ 14 | + (NSString *)cts_stringStatusWithVolume:(int const)volume muteState:(BOOL)muteState; 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Sources/volume-service/NSString+CTSSerializedVolumeStatus.m: -------------------------------------------------------------------------------- 1 | #import "NSString+CTSSerializedVolumeStatus.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @implementation NSString (CTSSerializedVolumeStatus) 6 | 7 | + (NSString *)cts_stringStatusWithVolume:(const int)volume muteState:(BOOL)muteState 8 | { 9 | NSString *status = nil; 10 | if (muteState && volume == 0) { 11 | status = @"-0"; 12 | } else { 13 | status = [NSString stringWithFormat:@"%d", (muteState ? -1 : 1) * volume]; 14 | } 15 | return status; 16 | } 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /Sources/volume-service/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "NSDictionary+CTSCommandLineArguments.h" 4 | #import "CTSBetterTouchToolWebServerConfiguration.h" 5 | #import "CTSVolumeService.h" 6 | 7 | static NSString * const kCalendarNameDefaultDelimiter = @","; 8 | 9 | int main(int argc, const char * argv[]) { 10 | @autoreleasepool { 11 | NSDictionary * const dictionary = 12 | [NSDictionary cts_dictionaryWithCommandLineArguments:[NSProcessInfo processInfo].arguments]; 13 | NSString * _Nullable const statusFilePath = dictionary[@"status-path"] ?: dictionary[@"p"]; 14 | NSString * _Nullable const useThresholdChangesString = dictionary[@"use-threshold"] ?: dictionary[@"u"]; 15 | NSString * _Nullable const thresholdsString = dictionary[@"thresholds"] ?: dictionary[@"t"]; 16 | NSString * _Nullable const webServerURLString = dictionary[@"btt-url"] ?: dictionary[@"u"]; 17 | NSString * _Nullable const webServerSharedSecret = dictionary[@"btt-secret"] ?: dictionary[@"s"]; 18 | NSString * _Nullable const widgetUUID = dictionary[@"widget-uuid"] ?: dictionary[@"w"]; 19 | 20 | if (!statusFilePath || 21 | !useThresholdChangesString || 22 | (widgetUUID && !webServerURLString)) { 23 | fputs("Usage: ./volume-service\n" 24 | " --status-path=, -p \n" 25 | " The file path to save the latest volume state. Intermediary directories must exist.\n\n" 26 | 27 | " --btt-url=, -u \n" 28 | " The optional base URL to BetterTouchTool's web server in the format `protocol://hostname:port`.\n" 29 | " If not specified, the service will not push updates to BetterTouchTool.\n\n" 30 | 31 | " --btt-secret=, -s \n" 32 | " The optional shared secret to authenticate with BetterTouchTool's web server.\n\n" 33 | 34 | " --widget-uuid=, -w \n" 35 | " The UUID of the BetterTouchTool widget to refresh on update pushes. If not specified, the\n" 36 | " service will not push updates to BetterTouchTool.\n\n" 37 | 38 | " --use-threshold=, -u \n" 39 | " Whether to only treat changes between volume appearance thresholds as valid events. See\n" 40 | " also, `--thresholds, -t`.\n\n" 41 | 42 | " --thresholds=, -t \n" 43 | " An optional list of comma-delimited, strictly-greater-than thresholds in descending order.\n" 44 | " If not specified, [65,32,0] is used instead, corresponding to the system thresholds.\n\n", 45 | stderr); 46 | return 1; 47 | } 48 | 49 | NSURL * const webServerURL = [NSURL URLWithString:webServerURLString]; 50 | CTSBetterTouchToolWebServerConfiguration * const configuration = 51 | [[CTSBetterTouchToolWebServerConfiguration alloc] initWithURL:webServerURL 52 | sharedSecret:webServerSharedSecret]; 53 | 54 | BOOL const useThresholdChanges = useThresholdChangesString.boolValue; 55 | NSMutableArray *thresholds = (useThresholdChanges ? [NSMutableArray array] : nil); 56 | if (useThresholdChanges) { 57 | NSArray * const thresholdStringComponents = [thresholdsString componentsSeparatedByString:@","]; 58 | for (NSString * const thresholdString in thresholdStringComponents) { 59 | [thresholds addObject:@([thresholdString integerValue])]; 60 | } 61 | if (thresholds.count == 0) { 62 | thresholds = [@[@65, @32, @0] mutableCopy]; 63 | } 64 | } 65 | 66 | NSURLSession * const URLSession = [NSURLSession sharedSession]; 67 | CTSVolumeService * const service = [[CTSVolumeService alloc] initWithStatusFilePath:statusFilePath 68 | URLSession:URLSession 69 | widgetUUID:widgetUUID 70 | webServerConfiguration:configuration 71 | volumeThresholds:thresholds]; 72 | [service start]; 73 | 74 | NSRunLoop * const runLoop = [NSRunLoop currentRunLoop]; 75 | [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 76 | while (service.isRunning) { 77 | [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 78 | } 79 | } 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /Tests/CTSBetterTouchToolWebServerConfigurationTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import "CTSBetterTouchToolWebServerConfiguration.h" 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface CTSBetterTouchToolWebServerConfigurationTests : XCTestCase 10 | 11 | @end 12 | 13 | @implementation CTSBetterTouchToolWebServerConfigurationTests 14 | 15 | - (void)testConfigurationInitialization 16 | { 17 | NSURL * const URL = [NSURL URLWithString:@"http://127.0.0.1:12345"]; 18 | NSString * const sharedSecret = @"a-very-secret-key"; 19 | CTSBetterTouchToolWebServerConfiguration * const configuration = 20 | [[CTSBetterTouchToolWebServerConfiguration alloc] initWithURL:URL sharedSecret:sharedSecret]; 21 | assertThat(configuration.URL, equalTo(URL)); 22 | assertThat(configuration.sharedSecret, equalTo(sharedSecret)); 23 | } 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /Tests/CTSControlStripServiceTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import 6 | #import "CTSWeakify.h" 7 | 8 | #import "CTSAudioToolboxControlStripServiceTestStub.h" 9 | #import "CTSCoreGraphicsEventControlStripServiceTestStub.h" 10 | #import "CTSControlStripService.h" 11 | 12 | @class CTSControlStripServiceTests; 13 | static CTSControlStripServiceTests *gControlStripServiceTestRunner = nil; 14 | static CTSAudioServicesMock *gAudioServicesMock = nil; 15 | static CTSCoreGraphicsEventMock *gCoreGraphicsEventMock = nil; 16 | 17 | OSStatus AudioServicesCreateSystemSoundID(CFURLRef inFileURL, 18 | SystemSoundID *outSystemSoundID) 19 | { 20 | return [gAudioServicesMock audioServicesCreateSystemSoundID:inFileURL outSystemSoundID:outSystemSoundID]; 21 | } 22 | 23 | void AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID) 24 | { 25 | [gAudioServicesMock audioServicesPlaySystemSound:inSystemSoundID]; 26 | } 27 | 28 | void CGEventPost(CGEventTapLocation tap, CGEventRef __nullable event) 29 | { 30 | [gCoreGraphicsEventMock cgEventPost:tap event:event]; 31 | } 32 | 33 | NS_ASSUME_NONNULL_BEGIN 34 | 35 | static NSEventModifierFlags const kSmallStepModifierFlags = (NSEventModifierFlagShift | NSEventModifierFlagOption); 36 | static NSString * const kFeedbackSoundFilePath = 37 | @"/System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/Resources/volume.aiff"; 38 | static SystemSoundID kFeedbackSoundID = 123; 39 | static NSString * const kSystemPreferencePaneBasePath = @"/System/Library/PreferencePanes/"; 40 | static NSString * const kSoundPreferencePaneFileName = @"Sound.prefPane"; 41 | static NSString * const kDisplaysPreferencePaneFileName = @"Displays.prefPane"; 42 | 43 | @interface CTSControlStripServiceTests : XCTestCase 44 | 45 | @property (nonatomic, strong, readwrite) NSWorkspace *workspaceMock; 46 | @property (nonatomic, assign, readwrite) BOOL createdFeedbackSoundID; 47 | @property (nonatomic, strong, readwrite) NSURL *retainedSoundSystemURL; 48 | 49 | @end 50 | 51 | @implementation CTSControlStripServiceTests 52 | 53 | - (void)setUp 54 | { 55 | [super setUp]; 56 | 57 | gAudioServicesMock = mock([CTSAudioServicesMock class]); 58 | gCoreGraphicsEventMock = mock([CTSCoreGraphicsEventMock class]); 59 | 60 | weakify(self); 61 | [[[given([gAudioServicesMock audioServicesCreateSystemSoundID:0 outSystemSoundID:0]) 62 | withMatcher:anything() forArgument:0] 63 | withMatcher:anything() forArgument:1] 64 | willDo:^id _Nonnull(NSInvocation * _Nonnull invocation) { 65 | strongify(self); 66 | NSURL * _Nullable URL = nil; 67 | [invocation getArgument:&URL atIndex:2]; 68 | NSURL * const expectedURL = [NSURL fileURLWithPath:kFeedbackSoundFilePath isDirectory:NO]; 69 | assertThat(URL, equalTo(expectedURL)); 70 | if ([URL isEqualTo:expectedURL]) { 71 | self.createdFeedbackSoundID = YES; 72 | } 73 | self.retainedSoundSystemURL = URL; // HACK: CFURLRef being double-freed due to this block. 74 | 75 | SystemSoundID *soundID; 76 | [invocation getArgument:&soundID atIndex:3]; 77 | *soundID = kFeedbackSoundID; 78 | 79 | return @(noErr); 80 | }]; 81 | 82 | self.workspaceMock = mock([NSWorkspace class]); 83 | } 84 | 85 | - (void)testServiceHandlesVolumeUpControl 86 | { 87 | XCTestExpectation * const expectation = 88 | [[XCTestExpectation alloc] initWithDescription:@"Events should be synthesized"]; 89 | expectation.expectedFulfillmentCount = 2; 90 | [self captureKeyPressWithKeyCode:NX_KEYTYPE_SOUND_UP 91 | shouldKeyDown:YES 92 | shouldUseSmallStep:NO 93 | expectation:expectation]; 94 | 95 | // Given the service is created with the volume up control type and feedback sounds enabled 96 | CTSControlStripService * const service = 97 | [[CTSControlStripService alloc] initWithControlType:CTSControlStripVolumeUpControl 98 | volumeFeedbackEnabled:YES 99 | modifierFlags:0 100 | workspace:self.workspaceMock]; 101 | 102 | // When it is started 103 | [service start]; 104 | 105 | // Then the service should synthesize and perform the expected key press events 106 | [self waitForExpectations:@[expectation] timeout:1.0]; 107 | // And no volume feedback sounds are played. 108 | [[[verifyCount(gAudioServicesMock, never()) 109 | withMatcher:anything() forArgument:0] 110 | withMatcher:anything() forArgument:1] 111 | audioServicesCreateSystemSoundID:0 outSystemSoundID:0]; 112 | } 113 | 114 | - (void)testServiceHandlesSmallStepBrightnessDownControl 115 | { 116 | XCTestExpectation * const expectation = 117 | [[XCTestExpectation alloc] initWithDescription:@"Events should be synthesized"]; 118 | expectation.expectedFulfillmentCount = 2; 119 | [self captureKeyPressWithKeyCode:NX_KEYTYPE_BRIGHTNESS_DOWN 120 | shouldKeyDown:YES 121 | shouldUseSmallStep:YES 122 | expectation:expectation]; 123 | 124 | // Given the service is created with the brightness down control type and small step modifiers 125 | CTSControlStripService * const service = 126 | [[CTSControlStripService alloc] initWithControlType:CTSControlStripBrightnessDownControl 127 | volumeFeedbackEnabled:YES 128 | modifierFlags:kSmallStepModifierFlags 129 | workspace:self.workspaceMock]; 130 | 131 | // When it is started 132 | [service start]; 133 | 134 | // Then the service should synthesize and perform the expected small step key press events 135 | [self waitForExpectations:@[expectation] timeout:1.0]; 136 | // And no volume feedback sounds are played. 137 | [[[verifyCount(gAudioServicesMock, never()) 138 | withMatcher:anything() forArgument:0] 139 | withMatcher:anything() forArgument:1] 140 | audioServicesCreateSystemSoundID:0 outSystemSoundID:0]; 141 | } 142 | 143 | - (void)testServiceHandlesKeyboardIlluminationDownControl 144 | { 145 | XCTestExpectation * const expectation = 146 | [[XCTestExpectation alloc] initWithDescription:@"Events should be synthesized"]; 147 | expectation.expectedFulfillmentCount = 2; 148 | [self captureKeyPressWithKeyCode:NX_KEYTYPE_ILLUMINATION_DOWN 149 | shouldKeyDown:YES 150 | shouldUseSmallStep:NO 151 | expectation:expectation]; 152 | 153 | // Given the service is created with the brightnes down control type and shift modifier 154 | CTSControlStripService * const service = 155 | [[CTSControlStripService alloc] initWithControlType:CTSControlStripBrightnessDownControl 156 | volumeFeedbackEnabled:YES 157 | modifierFlags:NSEventModifierFlagShift 158 | workspace:self.workspaceMock]; 159 | 160 | // When it is started 161 | [service start]; 162 | 163 | // Then the service should synthesize and perform the expected illumination key press events 164 | [self waitForExpectations:@[expectation] timeout:1.0]; 165 | // And no volume feedback sounds are played. 166 | [[[verifyCount(gAudioServicesMock, never()) 167 | withMatcher:anything() forArgument:0] 168 | withMatcher:anything() forArgument:1] 169 | audioServicesCreateSystemSoundID:0 outSystemSoundID:0]; 170 | } 171 | 172 | - (void)testServicePlaysVolumeFeedbackSounds 173 | { 174 | XCTestExpectation * const expectation = 175 | [[XCTestExpectation alloc] initWithDescription:@"Feedback sound should be played"]; 176 | [self capturePlaySystemSoundWithExpectation:expectation]; 177 | 178 | // Given the service is created with the volume up control type, feedback sounds enabled, and shift modifier 179 | CTSControlStripService * const service = 180 | [[CTSControlStripService alloc] initWithControlType:CTSControlStripVolumeUpControl 181 | volumeFeedbackEnabled:YES 182 | modifierFlags:NSEventModifierFlagShift 183 | workspace:self.workspaceMock]; 184 | // And no feedback sound ID was created yet 185 | assertThatBool(self.createdFeedbackSoundID, isFalse()); 186 | 187 | // When it is started 188 | [service start]; 189 | 190 | // Then the service should have played volume feedback sounds. 191 | assertThatBool(self.createdFeedbackSoundID, isTrue()); 192 | // DRAGON: OCMockito doesn't get the correct sound ID value with direct verification... 193 | [self waitForExpectations:@[expectation] timeout:1.0]; 194 | } 195 | 196 | - (void)testServiceOpensVolumePreferencePane 197 | { 198 | // Given the service is created with the volume down control type and the option modifier 199 | CTSControlStripService * const service = 200 | [[CTSControlStripService alloc] initWithControlType:CTSControlStripVolumeDownControl 201 | volumeFeedbackEnabled:YES 202 | modifierFlags:NSEventModifierFlagOption 203 | workspace:self.workspaceMock]; 204 | 205 | // When it is started 206 | [service start]; 207 | 208 | // Then the service should open the volume preference pane. 209 | NSString * const preferencePanePath = 210 | [kSystemPreferencePaneBasePath stringByAppendingPathComponent:kSoundPreferencePaneFileName]; 211 | [verify(self.workspaceMock) openFile:preferencePanePath]; 212 | } 213 | 214 | - (void)testServiceOpensDisplaysPreferencePane 215 | { 216 | // Given the service is created with the volume down control type and the option modifier 217 | CTSControlStripService * const service = 218 | [[CTSControlStripService alloc] initWithControlType:CTSControlStripBrightnessDownControl 219 | volumeFeedbackEnabled:YES 220 | modifierFlags:NSEventModifierFlagOption 221 | workspace:self.workspaceMock]; 222 | 223 | // When it is started 224 | [service start]; 225 | 226 | // Then the service should open the volume preference pane. 227 | NSString * const preferencePanePath = 228 | [kSystemPreferencePaneBasePath stringByAppendingPathComponent:kDisplaysPreferencePaneFileName]; 229 | [verify(self.workspaceMock) openFile:preferencePanePath]; 230 | } 231 | 232 | 233 | #pragma mark - Utils 234 | 235 | - (void)captureKeyPressWithKeyCode:(CGKeyCode const)keyCode 236 | shouldKeyDown:(BOOL const)shouldKeyDown 237 | shouldUseSmallStep:(BOOL const)shouldUseSmallStep 238 | expectation:(XCTestExpectation * const)expectation 239 | { 240 | 241 | __block BOOL shouldKeyDownFlag = shouldKeyDown; 242 | [[givenVoid([gCoreGraphicsEventMock cgEventPost:kCGHIDEventTap event:0]) withMatcher:anything() forArgument:1] 243 | willDo:^id _Nonnull(NSInvocation * _Nonnull invocation) { 244 | // DRAGON: OCMockito fails to get event ref arguments through `mkt_arguments`. 245 | CGEventRef _Nullable keyDownRef = nil; 246 | [invocation getArgument:&keyDownRef atIndex:3]; 247 | 248 | assertThat((__bridge id)keyDownRef, notNilValue()); 249 | if (!keyDownRef) { 250 | return nil; 251 | } 252 | 253 | NSEvent * _Nullable const keyDownEvent = [NSEvent eventWithCGEvent:keyDownRef]; 254 | assertThat(keyDownEvent, notNilValue()); 255 | 256 | NSEventModifierFlags const modifier = (shouldKeyDownFlag ? NX_KEYDOWN : NX_KEYUP); 257 | NSEventModifierFlags const smallStepModifier = (shouldUseSmallStep ? kSmallStepModifierFlags : 0); 258 | 259 | assertThatUnsignedInteger(keyDownEvent.type, equalToUnsignedInteger(NSEventTypeSystemDefined)); 260 | assertThatBool(CGPointEqualToPoint(keyDownEvent.locationInWindow, CGPointZero), isTrue()); 261 | assertThatUnsignedInteger(keyDownEvent.modifierFlags, equalToUnsignedInteger(modifier | smallStepModifier)); 262 | assertThatDouble(keyDownEvent.timestamp, equalToDouble(0)); 263 | assertThatShort(keyDownEvent.subtype, equalToShort(8)); 264 | assertThatInteger(keyDownEvent.data1, equalToInteger((keyCode << 16) | (modifier << 8))); 265 | assertThatInteger(keyDownEvent.data2, equalToInteger(-1)); 266 | 267 | shouldKeyDownFlag = NO; 268 | [expectation fulfill]; 269 | return nil; 270 | }]; 271 | } 272 | 273 | - (void)capturePlaySystemSoundWithExpectation:(XCTestExpectation * const)expectation 274 | { 275 | [[givenVoid([gAudioServicesMock audioServicesPlaySystemSound:0]) 276 | withMatcher:anything() forArgument:0] willDo:^id _Nonnull(NSInvocation * _Nonnull invocation) { 277 | SystemSoundID soundID; 278 | [invocation getArgument:&soundID atIndex:2]; 279 | assertThatInteger(soundID, equalToInteger(kFeedbackSoundID)); 280 | 281 | [expectation fulfill]; 282 | return nil; 283 | }]; 284 | } 285 | 286 | @end 287 | 288 | NS_ASSUME_NONNULL_END 289 | -------------------------------------------------------------------------------- /Tests/EKEventCTSVisibilityTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import 6 | 7 | #import "EKEvent+CTSVisibility.h" 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | @interface EKEventConcreteMock : EKEvent 12 | 13 | @property (nonatomic, assign, readwrite) EKEventAvailability availability; 14 | @property (nonatomic, assign, readwrite) EKEventStatus status; 15 | 16 | @end 17 | 18 | @implementation EKEventConcreteMock 19 | 20 | @synthesize availability = _availability, status = _status; 21 | 22 | @end 23 | 24 | @interface EKEventCTSVisibilityTests : XCTestCase 25 | 26 | @end 27 | 28 | @implementation EKEventCTSVisibilityTests 29 | 30 | - (void)testVisibilityForAvailability 31 | { 32 | // Given an event 33 | EKEventConcreteMock * const event = [[EKEventConcreteMock alloc] init]; 34 | // With a non-canceled status 35 | event.status = EKEventStatusConfirmed; 36 | 37 | // When the availability is free 38 | event.availability = EKEventAvailabilityFree; 39 | // Then the event visibility should be NO. 40 | assertThatBool(event.isVisible, isFalse()); 41 | 42 | // And When the availability is tenative 43 | event.availability = EKEventAvailabilityTentative; 44 | // Then the event visibility should be YES. 45 | assertThatBool(event.isVisible, isTrue()); 46 | 47 | // And When the availability is not supported 48 | event.availability = EKEventAvailabilityNotSupported; 49 | // Then the event visibility should be YES. 50 | assertThatBool(event.isVisible, isTrue()); 51 | 52 | // And When the availability is busy 53 | event.availability = EKEventAvailabilityBusy; 54 | // Then the event visibility should be YES. 55 | assertThatBool(event.isVisible, isTrue()); 56 | } 57 | 58 | - (void)testVisibilityForStatus 59 | { 60 | // Given an event 61 | EKEventConcreteMock * const event = [[EKEventConcreteMock alloc] init]; 62 | // When the event status is canceled 63 | event.status = EKEventStatusCanceled; 64 | // Then the event availability should be NO regardless of availability. 65 | event.availability = EKEventAvailabilityFree; 66 | assertThatBool(event.isVisible, isFalse()); 67 | event.availability = EKEventAvailabilityTentative; 68 | assertThatBool(event.isVisible, isFalse()); 69 | event.availability = EKEventAvailabilityNotSupported; 70 | assertThatBool(event.isVisible, isFalse()); 71 | event.availability = EKEventAvailabilityBusy; 72 | assertThatBool(event.isVisible, isFalse()); 73 | } 74 | 75 | 76 | @end 77 | 78 | NS_ASSUME_NONNULL_END 79 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Modules: -------------------------------------------------------------------------------- 1 | Versions/Current/Modules -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/OCHamcrest: -------------------------------------------------------------------------------- 1 | Versions/Current/OCHamcrest -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCAllOf.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Calculates the logical conjunction of multiple matchers. 11 | * @discussion Evaluation is shortcut, so subsequent matchers are not called if an earlier matcher 12 | * returns NO. 13 | */ 14 | @interface HCAllOf : HCDiagnosingMatcher 15 | 16 | - (instancetype)initWithMatchers:(NSArray> *)matchers NS_DESIGNATED_INITIALIZER; 17 | - (instancetype)init NS_UNAVAILABLE; 18 | 19 | @end 20 | 21 | 22 | FOUNDATION_EXPORT id HC_allOfIn(NSArray> *matchers); 23 | 24 | #ifndef HC_DISABLE_SHORT_SYNTAX 25 | /*! 26 | * @abstract Creates a matcher that matches when the examined object matches all of the 27 | * specified matchers. 28 | * @param matchers An array of matchers. Any element that is not a matcher is implicitly wrapped in 29 | * an equalTo matcher to check for equality. 30 | * @discussion 31 | * Example
32 | *
assertThat(\@"myValue", allOfIn(\@[startsWith(\@"my"), containsSubstring(\@"Val")]))
33 | * 34 | * Name Clash
35 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 36 | * HC_allOfIn instead. 37 | */ 38 | static inline id allOfIn(NSArray *matchers) 39 | { 40 | return HC_allOfIn(matchers); 41 | } 42 | #endif 43 | 44 | 45 | FOUNDATION_EXPORT id HC_allOf(id matchers, ...) NS_REQUIRES_NIL_TERMINATION; 46 | 47 | #ifndef HC_DISABLE_SHORT_SYNTAX 48 | /*! 49 | * @abstract Creates a matcher that matches when the examined object matches all of the 50 | * specified matchers. 51 | * @param matchers... A comma-separated list of matchers ending with nil. Any argument 52 | * that is not a matcher is implicitly wrapped in an equalTo matcher to check for equality. 53 | * @discussion 54 | * Example
55 | *
assertThat(\@"myValue", allOf(startsWith(\@"my"), containsSubstring(\@"Val"), nil))
56 | * 57 | * Name Clash
58 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 59 | * HC_allOf instead. 60 | */ 61 | #define allOf(matchers...) HC_allOf(matchers) 62 | #endif 63 | 64 | NS_ASSUME_NONNULL_END 65 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCAnyOf.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Calculates the logical disjunction of multiple matchers. 11 | * @discussion Evaluation is shortcut, so subsequent matchers are not called if an earlier matcher 12 | * returns NO. 13 | */ 14 | @interface HCAnyOf : HCBaseMatcher 15 | 16 | - (instancetype)initWithMatchers:(NSArray> *)matchers NS_DESIGNATED_INITIALIZER; 17 | - (instancetype)init NS_UNAVAILABLE; 18 | 19 | @end 20 | 21 | FOUNDATION_EXPORT id HC_anyOfIn(NSArray *matchers); 22 | 23 | #ifndef HC_DISABLE_SHORT_SYNTAX 24 | /*! 25 | * @abstract Creates a matcher that matches when the examined object matches any of the 26 | * specified matchers. 27 | * @param matchers An array of matchers. Any element that is not a matcher is implicitly wrapped in 28 | * an equalTo matcher to check for equality. 29 | * @discussion 30 | * Example
31 | *
assertThat(\@"myValue", allOf(\@[startsWith(\@"foo"), containsSubstring(\@"Val")]))
32 | * 33 | * Name Clash
34 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 35 | * HC_anyOf instead. 36 | */ 37 | static inline id anyOfIn(NSArray *matchers) 38 | { 39 | return HC_anyOfIn(matchers); 40 | } 41 | #endif 42 | 43 | FOUNDATION_EXPORT id HC_anyOf(id matchers, ...) NS_REQUIRES_NIL_TERMINATION; 44 | 45 | #ifndef HC_DISABLE_SHORT_SYNTAX 46 | /*! 47 | * @abstract Creates a matcher that matches when the examined object matches any of the 48 | * specified matchers. 49 | * @param matchers... A comma-separated list of matchers ending with nil. Any argument 50 | * that is not a matcher is implicitly wrapped in an equalTo matcher to check for equality. 51 | * @discussion 52 | * Example
53 | *
assertThat(\@"myValue", allOf(startsWith(\@"foo"), containsSubstring(\@"Val"), nil))
54 | * 55 | * Name Clash
56 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 57 | * HC_anyOf instead. 58 | */ 59 | #define anyOf(matchers...) HC_anyOf(matchers) 60 | #endif 61 | 62 | NS_ASSUME_NONNULL_END 63 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCArgumentCaptor.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches anything, capturing all values. 11 | * @discussion This matcher captures all values it was given to match, and always evaluates to 12 | * YES. Use it to capture argument values for further assertions. 13 | * 14 | * Unlike other matchers, this matcher is not idempotent. It should be created outside of any 15 | * expression so that it can be queried for the items it captured. 16 | */ 17 | @interface HCArgumentCaptor : HCIsAnything 18 | 19 | /*! 20 | * @abstract Returns the captured value. 21 | * @discussion If -matches: was called more than once then this property returns the 22 | * last captured value. 23 | * 24 | * If -matches: was never invoked and so no value was captured, this property returns 25 | * nil. But if nil was captured, this property returns NSNull. 26 | */ 27 | @property (nullable, nonatomic, readonly) id value; 28 | 29 | /*! 30 | * @abstract Returns all captured values. 31 | * @discussion Returns an array containing all captured values, in the order in which they were 32 | * captured. nil values are converted to NSNull. 33 | */ 34 | @property (nonatomic, readonly) NSArray *allValues; 35 | 36 | /*! 37 | * @abstract Determines whether subsequent matched values are captured. 38 | * @discussion YES by default. 39 | */ 40 | @property (nonatomic, assign) BOOL captureEnabled; 41 | 42 | @end 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCAssertThat.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | @protocol HCMatcher; 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | /*! 11 | * @header 12 | * Assertion macros for using matchers in testing frameworks. 13 | * Unmet assertions are reported to the HCTestFailureReporterChain. 14 | */ 15 | 16 | 17 | FOUNDATION_EXPORT void HC_assertThatWithLocation(id testCase, _Nullable id actual, id matcher, 18 | const char *fileName, int lineNumber); 19 | 20 | #define HC_assertThat(actual, matcher) \ 21 | HC_assertThatWithLocation(self, actual, matcher, __FILE__, __LINE__) 22 | 23 | #ifndef HC_DISABLE_SHORT_SYNTAX 24 | /*! 25 | * @abstract assertThat(actual, matcher) - 26 | * Asserts that actual value satisfies matcher. 27 | * @param actual The object to evaluate as the actual value. 28 | * @param matcher The matcher to satisfy as the expected condition. 29 | * @discussion assertThat passes the actual value to the matcher for evaluation. If the matcher is 30 | * not satisfied, it is reported to the HCTestFailureReporterChain. 31 | * 32 | * Use assertThat in test case methods. It's designed to integrate with XCTest and other testing 33 | * frameworks where individual tests are executed as methods. 34 | * 35 | * Name Clash
36 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 37 | * HC_assertThat instead. 38 | */ 39 | #define assertThat(actual, matcher) HC_assertThat(actual, matcher) 40 | #endif 41 | 42 | 43 | typedef _Nonnull id (^HCFutureValue)(void); 44 | 45 | FOUNDATION_EXPORT void HC_assertWithTimeoutAndLocation(id testCase, NSTimeInterval timeout, 46 | HCFutureValue actualBlock, id matcher, 47 | const char *fileName, int lineNumber); 48 | 49 | #define HC_assertWithTimeout(timeout, actualBlock, matcher) \ 50 | HC_assertWithTimeoutAndLocation(self, timeout, actualBlock, matcher, __FILE__, __LINE__) 51 | 52 | #define HC_thatEventually(actual) ^{ return actual; } 53 | 54 | #ifndef HC_DISABLE_SHORT_SYNTAX 55 | /*! 56 | * @abstract assertWithTimeout(timeout, actualBlock, matcher) - 57 | * Asserts that a value provided by a block will satisfy matcher within the specified time. 58 | * @param timeout Maximum time to wait for passing behavior, specified in seconds. 59 | * @param actualBlock A block providing the object to repeatedly evaluate as the actual value. 60 | * @param matcher The matcher to satisfy as the expected condition. 61 | * @discussion assertWithTimeout polls a value provided by a block to asynchronously 62 | * satisfy the matcher. The block is evaluated repeatedly for an actual value, which is passed to 63 | * the matcher for evaluation. If the matcher is not satisfied within the timeout, it is reported to 64 | * the HCTestFailureReporterChain. 65 | * 66 | * An easy way of providing the actualBlock is to use the macro thatEventually. 67 | * 68 | * Name Clash
69 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 70 | * HC_assertWithTimeout instead. 71 | */ 72 | #define assertWithTimeout(timeout, actualBlock, matcher) HC_assertWithTimeout(timeout, actualBlock, matcher) 73 | 74 | 75 | /*! 76 | * @abstract thatEventually(actual) - 77 | * Evaluates actual value at future time. 78 | * @param actual The object to evaluate as the actual value. 79 | * @discussion Wraps actual in a block so that it can be repeatedly evaluated by 80 | * assertWithTimeout. 81 | * 82 | * Name Clash
83 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 84 | * HC_thatEventually instead. 85 | */ 86 | #define thatEventually(actual) HC_thatEventually(actual) 87 | #endif 88 | 89 | 90 | /*! 91 | * @abstract "Expected , but " 92 | * @discussion Helper function to let you describe mismatches the way assertThat does. 93 | */ 94 | FOUNDATION_EXPORT NSString *HCDescribeMismatch(id matcher, id actual); 95 | 96 | NS_ASSUME_NONNULL_END 97 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCBaseDescription.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | #import 6 | 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | /*! 11 | * @abstract Base class for all HCDescription implementations. 12 | */ 13 | @interface HCBaseDescription : NSObject 14 | @end 15 | 16 | 17 | /*! 18 | * @abstract Methods that must be provided by subclasses of HCBaseDescription. 19 | */ 20 | @interface HCBaseDescription (SubclassResponsibility) 21 | 22 | /*! 23 | * @abstract Appends the specified string to the description. 24 | */ 25 | - (void)append:(NSString *)str; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCBaseMatcher.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | #import 6 | 7 | #define HC_ABSTRACT_METHOD [self subclassResponsibility:_cmd] 8 | 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | /*! 13 | * @abstract Base class for all HCMatcher implementations. 14 | * @discussion Simple matchers can just subclass HCBaseMatcher and implement -matches: 15 | * and -describeTo:. But if the matching algorithm has several "no match" paths, 16 | * consider subclassing HCDiagnosingMatcher instead. 17 | */ 18 | @interface HCBaseMatcher : NSObject 19 | 20 | /*! @abstract Raises exception that command (a pseudo-abstract method) is not implemented. */ 21 | - (void)subclassResponsibility:(SEL)command; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCClassMatcher.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface HCClassMatcher : HCBaseMatcher 10 | 11 | @property (nonatomic, strong, readonly) Class theClass; 12 | 13 | - (instancetype)initWithClass:(Class)aClass NS_DESIGNATED_INITIALIZER; 14 | - (instancetype)init NS_UNAVAILABLE; 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCCollect.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | #import 7 | 8 | @protocol HCMatcher; 9 | 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /*! 14 | * @abstract Returns an array of values from a variable-length comma-separated list terminated 15 | * by nil. 16 | */ 17 | FOUNDATION_EXPORT NSArray * HCCollectItems(id item, va_list args); 18 | 19 | /*! 20 | * @abstract Returns an array of matchers from a mixed array of items and matchers. 21 | * @discussion Each item is wrapped in HCWrapInMatcher to transform non-matcher items into equality 22 | * matchers. 23 | */ 24 | FOUNDATION_EXPORT NSArray> * HCWrapIntoMatchers(NSArray *items); 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCConformsToProtocol.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | // Contribution by Todd Farrell 4 | 5 | #import 6 | 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | /*! 11 | * @abstract Matches objects that conform to specified protocol. 12 | */ 13 | @interface HCConformsToProtocol : HCBaseMatcher 14 | 15 | - (instancetype)initWithProtocol:(Protocol *)protocol NS_DESIGNATED_INITIALIZER; 16 | - (instancetype)init NS_UNAVAILABLE; 17 | 18 | @end 19 | 20 | 21 | FOUNDATION_EXPORT id HC_conformsTo(Protocol *aProtocol); 22 | 23 | #ifndef HC_DISABLE_SHORT_SYNTAX 24 | /*! 25 | * @abstract Creates a matcher that matches when the examined object conforms to the specified 26 | * protocol. 27 | * @param aProtocol The protocol to compare against as the expected protocol. 28 | * @discussion 29 | * Example
30 | *
assertThat(myObject, conformsTo(\@protocol(NSCoding))
31 | * 32 | * Name Clash
33 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 34 | * HC_conformsTo instead. 35 | */ 36 | static inline id conformsTo(Protocol *aProtocol) 37 | { 38 | return HC_conformsTo(aProtocol); 39 | } 40 | #endif 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCDescribedAs.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Provides a custom description to another matcher. 11 | */ 12 | @interface HCDescribedAs : HCBaseMatcher 13 | 14 | - (instancetype)initWithDescription:(NSString *)description 15 | forMatcher:(id )matcher 16 | overValues:(NSArray *)templateValues NS_DESIGNATED_INITIALIZER; 17 | - (instancetype)init NS_UNAVAILABLE; 18 | 19 | @end 20 | 21 | 22 | FOUNDATION_EXPORT id HC_describedAs(NSString *description, id matcher, ...) NS_REQUIRES_NIL_TERMINATION; 23 | 24 | #ifndef HC_DISABLE_SHORT_SYNTAX 25 | /*! 26 | * @abstract Wraps an existing matcher, overriding its description with that specified. All other 27 | * functions are delegated to the decorated matcher, including its mismatch description. 28 | * @param description The new description for the wrapped matcher. 29 | * @param matcher The matcher to wrap, followed by a comma-separated list of substitution 30 | * values ending with nil. 31 | * @discussion The description may contain substitution placeholders %0, %1, etc. These will be 32 | * replaced by any values that follow the matcher. 33 | * 34 | * Name Clash
35 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 36 | * HC_describedAs instead. 37 | */ 38 | #define describedAs(description, matcher, ...) HC_describedAs(description, matcher, ##__VA_ARGS__) 39 | #endif 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCDescription.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract A description of an HCMatcher. 11 | * @discussion An HCMatcher will describe itself to a description which can later be used for reporting. 12 | */ 13 | @protocol HCDescription 14 | 15 | /*! 16 | * @abstract Appends some plain text to the description. 17 | * @return self, for chaining. 18 | */ 19 | - (id )appendText:(NSString *)text; 20 | 21 | /*! 22 | * @abstract Appends description of specified value to description. 23 | * @discussion If the value implements the HCSelfDescribing protocol, then it will be used. 24 | * @return self, for chaining. 25 | */ 26 | - (id )appendDescriptionOf:(nullable id)value; 27 | 28 | /*! 29 | * @abstract Appends a list of objects to the description. 30 | * @return self, for chaining. 31 | */ 32 | - (id )appendList:(NSArray *)values 33 | start:(NSString *)start 34 | separator:(NSString *)separator 35 | end:(NSString *)end; 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCDiagnosingMatcher.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Base class for matchers that generate mismatch descriptions during the matching. 11 | * @discussion Some matching algorithms have several "no match" paths. It helps to make the mismatch 12 | * description as precise as possible, but we don't want to have to repeat the matching logic to do 13 | * so. For such matchers, subclass HCDiagnosingMatcher and implement HCMatcher's 14 | * -matches:describingMismatchTo:. 15 | */ 16 | @interface HCDiagnosingMatcher : HCBaseMatcher 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCEvery.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if every item in a collection satisfies a nested matcher. 11 | */ 12 | @interface HCEvery : HCDiagnosingMatcher 13 | 14 | @property (nonatomic, strong, readonly) id matcher; 15 | 16 | - (instancetype)initWithMatcher:(id )matcher NS_DESIGNATED_INITIALIZER; 17 | - (instancetype)init NS_UNAVAILABLE; 18 | 19 | @end 20 | 21 | 22 | FOUNDATION_EXPORT id HC_everyItem(id itemMatcher); 23 | 24 | #ifndef HC_DISABLE_SHORT_SYNTAX 25 | /*! 26 | * @abstract Creates a matcher for collections that matches when the examined collection's items are 27 | * all matched by the specified matcher. 28 | * @param itemMatcher The matcher to apply to every item provided by the examined collection. 29 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 30 | * performing a single pass. 31 | * 32 | * Example
33 | *
assertThat(\@[\@"bar", \@"baz"], everyItem(startsWith(\@"ba")))
34 | * 35 | * Name Clash
36 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 37 | * HC_everyItem instead. 38 | */ 39 | static inline id everyItem(id itemMatcher) 40 | { 41 | return HC_everyItem(itemMatcher); 42 | } 43 | #endif 44 | 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCHasCount.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if collection size satisfies a nested matcher. 11 | */ 12 | @interface HCHasCount : HCBaseMatcher 13 | 14 | - (instancetype)initWithMatcher:(id )countMatcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_hasCount(id countMatcher); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that matches when the examined object's -count method 25 | * returns a value that satisfies the specified matcher. 26 | * @param countMatcher A matcher for the count of an examined collection. 27 | * @discussion 28 | * Example
29 | *
assertThat(\@[\@"foo", \@"bar"], hasCount(equalTo(@2)))
30 | * 31 | * Name Clash
32 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 33 | * HC_hasCount instead. 34 | */ 35 | static inline id hasCount(id countMatcher) 36 | { 37 | return HC_hasCount(countMatcher); 38 | } 39 | #endif 40 | 41 | 42 | FOUNDATION_EXPORT id HC_hasCountOf(NSUInteger count); 43 | 44 | #ifndef HC_DISABLE_SHORT_SYNTAX 45 | /*! 46 | * @abstract Creates a matcher that matches when the examined object's -count method 47 | * returns a value that equals the specified value. 48 | * @param value Value to compare against as the expected count. 49 | * @discussion 50 | * Example
51 | *
assertThat(\@[\@"foo", \@"bar"], hasCountOf(2))
52 | * 53 | * Name Clash
54 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 55 | * HC_hasCountOf instead. 56 | */ 57 | static inline id hasCountOf(NSUInteger value) 58 | { 59 | return HC_hasCountOf(value); 60 | } 61 | #endif 62 | 63 | NS_ASSUME_NONNULL_END 64 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCHasDescription.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches objects whose description satisfies a nested matcher. 11 | */ 12 | @interface HCHasDescription : HCInvocationMatcher 13 | 14 | - (instancetype)initWithDescription:(id )descriptionMatcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)initWithInvocation:(NSInvocation *)anInvocation matching:(id )aMatcher NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_hasDescription(id descriptionMatcher); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that matches when the examined object's -description 25 | * satisfies the specified matcher. 26 | * @param descriptionMatcher The matcher used to verify the description result, or an expected value 27 | * for equalTo matching. 28 | * @discussion If descriptionMatcher is not a matcher, it is implicitly wrapped in 29 | * an equalTo matcher to check for equality. 30 | * 31 | * Examples
32 | *
assertThat(myObject, hasDescription(equalTo(\@"foo"))
33 | *
assertThat(myObject, hasDescription(\@"foo"))
34 | * 35 | * Name Clash
36 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 37 | * HC_hasDescription instead. 38 | */ 39 | static inline id hasDescription(id descriptionMatcher) 40 | { 41 | return HC_hasDescription(descriptionMatcher); 42 | } 43 | #endif 44 | 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCHasProperty.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | // Contribution by Justin Shacklette 4 | 5 | #import 6 | 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | /*! 11 | * @abstract Matches objects whose "property" (or simple method) satisfies a nested matcher. 12 | */ 13 | @interface HCHasProperty : HCDiagnosingMatcher 14 | 15 | - (instancetype)initWithProperty:(NSString *)propertyName value:(id )valueMatcher NS_DESIGNATED_INITIALIZER; 16 | - (instancetype)init NS_UNAVAILABLE; 17 | 18 | @end 19 | 20 | 21 | FOUNDATION_EXPORT id HC_hasProperty(NSString *propertyName, _Nullable id valueMatcher); 22 | 23 | #ifndef HC_DISABLE_SHORT_SYNTAX 24 | /*! 25 | * @abstract Creates a matcher that matches when the examined object has an instance method with the 26 | * specified name whose return value satisfies the specified matcher. 27 | * @param propertyName The name of an instance method without arguments that returns an object. 28 | * @param valueMatcher The matcher to satisfy for the return value, or an expected value for 29 | * equalTo matching. 30 | * @discussion Note: While this matcher factory is called "hasProperty", it applies to the return 31 | * values of any instance methods without arguments, not just properties. 32 | * 33 | * Examples
34 | *
assertThat(person, hasProperty(\@"firstName", equalTo(\@"Joe")))
35 | *
assertThat(person, hasProperty(\@"firstName", \@"Joe"))
36 | * 37 | * Name Clash
38 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 39 | * HC_hasProperty instead. 40 | */ 41 | static inline id hasProperty(NSString *propertyName, _Nullable id valueMatcher) 42 | { 43 | return HC_hasProperty(propertyName, valueMatcher); 44 | } 45 | #endif 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCInvocationMatcher.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Supporting class for matching a feature of an object. 11 | * @discussion Tests whether the result of passing the specified invocation to the value satisfies 12 | * the specified matcher. 13 | */ 14 | @interface HCInvocationMatcher : HCBaseMatcher 15 | 16 | 17 | /*! 18 | * @abstract Determines whether a mismatch will be described in short form. 19 | * @discussion Default is long form, which describes the object, the name of the invocation, and the 20 | * sub-matcher's mismatch diagnosis. Short form only has the sub-matcher's mismatch diagnosis. 21 | */ 22 | @property (nonatomic, assign) BOOL shortMismatchDescription; 23 | 24 | /*! 25 | * @abstract Initializes a newly allocated HCInvocationMatcher with an invocation and a matcher. 26 | */ 27 | - (instancetype)initWithInvocation:(NSInvocation *)anInvocation matching:(id )aMatcher NS_DESIGNATED_INITIALIZER; 28 | - (instancetype)init NS_UNAVAILABLE; 29 | 30 | /*! 31 | * @abstract Invokes stored invocation on the specified item and returns the result. 32 | */ 33 | - (id)invokeOn:(id)item; 34 | 35 | /*! 36 | * @abstract Returns string representation of the invocation's selector. 37 | */ 38 | - (NSString *)stringFromSelector; 39 | 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIs.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Decorates another matcher. 11 | */ 12 | @interface HCIs : HCBaseMatcher 13 | 14 | - (instancetype)initWithMatcher:(id )matcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_is(_Nullable id value); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Wraps an existing matcher, or provides a shortcut to the frequently 25 | * used is(equalTo(x)). 26 | * @param value The matcher to satisfy, or an expected value for equalTo matching. 27 | * @discussion 28 | * If valueis a matcher, its behavior is retained, but the test may be slightly more 29 | * expressive. For example: 30 | *
    31 | *
  • assertThat(\@(value), equalTo(\@5))
  • 32 | *
  • assertThat(\@(value), is(equalTo(\@5)))
  • 33 | *
34 | * 35 | * If valueis not a matcher, it is wrapped in an equalTo matcher. This makes the 36 | * following statements equivalent: 37 | *
    38 | *
  • assertThat(cheese, equalTo(smelly))
  • 39 | *
  • assertThat(cheese, is(equalTo(smelly)))
  • 40 | *
  • assertThat(cheese, is(smelly))
  • 41 | *
42 | * 43 | * Choose the style that makes your expression most readable. This will vary depending on context. 44 | * 45 | * Name Clash
46 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 47 | * HC_is instead. 48 | */ 49 | static inline id is(_Nullable id value) 50 | { 51 | return HC_is(value); 52 | } 53 | #endif 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsAnything.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches anything. 11 | */ 12 | @interface HCIsAnything : HCBaseMatcher 13 | 14 | - (instancetype)init; 15 | - (instancetype)initWithDescription:(NSString *)description NS_DESIGNATED_INITIALIZER; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_anything(void); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that always matches, regardless of the examined object. 25 | * @discussion 26 | * Name Clash
27 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 28 | * HC_anything instead. 29 | */ 30 | static inline id anything(void) 31 | { 32 | return HC_anything(); 33 | } 34 | #endif 35 | 36 | 37 | FOUNDATION_EXPORT id HC_anythingWithDescription(NSString *description); 38 | 39 | #ifndef HC_DISABLE_SHORT_SYNTAX 40 | /*! 41 | * @abstract Creates a matcher that matches anything, regardless of the examined object, but 42 | * describes itself with the specified NSString. 43 | * @param description A meaningful string used to describe this matcher. 44 | * @discussion 45 | * Name Clash
46 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 47 | * HC_anything instead. 48 | */ 49 | static inline id anythingWithDescription(NSString *description) 50 | { 51 | return HC_anythingWithDescription(description); 52 | } 53 | #endif 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsCloseTo.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matchers numbers close to a value, within a delta range. 11 | */ 12 | @interface HCIsCloseTo : HCBaseMatcher 13 | 14 | - (instancetype)initWithValue:(double)value delta:(double)delta NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_closeTo(double value, double delta); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher for NSNumbers that matches when the examined number is close to the 25 | * specified value, within the specified delta. 26 | * @param value The expected value of matching numbers. 27 | * @param delta The delta within which matches will be allowed. 28 | * @discussion Invokes -doubleValue on the examined number to get its value. 29 | * 30 | * Example
31 | *
assertThat(\@1.03, closeTo(1.0, 0.03)
32 | * 33 | * Name Clash
34 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 35 | * HC_closeTo instead. 36 | */ 37 | static inline id closeTo(double value, double delta) 38 | { 39 | return HC_closeTo(value, delta); 40 | } 41 | #endif 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsCollectionContaining.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if any item in a collection satisfies a nested matcher. 11 | */ 12 | @interface HCIsCollectionContaining : HCDiagnosingMatcher 13 | 14 | - (instancetype)initWithMatcher:(id )elementMatcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_hasItem(id itemMatcher); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract hasItem(itemMatcher) - 25 | * Creates a matcher for collections that matches when at least one item in the examined collection 26 | * satisfies the specified matcher. 27 | * @param itemMatcher The matcher to apply to collection elements, or an expected value 28 | * for equalTo matching. 29 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 30 | * performing a single pass. 31 | * 32 | * If itemMatcher is not a matcher, it is implicitly wrapped in an equalTo matcher 33 | * to check for equality. 34 | * 35 | * Example
36 | *
assertThat(\@[\@1, \@2, \@3], hasItem(equalTo(\@2)))
37 | * 38 | *
assertThat(\@[\@1, \@2, \@3], hasItem(\@2))
39 | * 40 | * Name Clash
41 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 42 | * HC_hasItem instead. 43 | */ 44 | #define hasItem HC_hasItem 45 | #endif 46 | 47 | 48 | FOUNDATION_EXPORT id HC_hasItemsIn(NSArray *itemMatchers); 49 | 50 | #ifndef HC_DISABLE_SHORT_SYNTAX 51 | /*! 52 | * @abstract Creates a matcher for collections that matches when all specified matchers are 53 | * satisfied by any item in the examined collection. 54 | * @param itemMatchers An array of matchers. Any element that is not a matcher is implicitly wrapped 55 | * in an equalTo matcher to check for equality. 56 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 57 | * performing one pass for each matcher. 58 | * 59 | * Example
60 | *
assertThat(\@[\@"foo", \@"bar", \@"baz"], hasItems(\@[endsWith(\@"z"), endsWith(\@"o")]))
61 | * 62 | * Name Clash
63 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 64 | * HC_hasItemsIn instead. 65 | */ 66 | static inline id hasItemsIn(NSArray *itemMatchers) 67 | { 68 | return HC_hasItemsIn(itemMatchers); 69 | } 70 | #endif 71 | 72 | 73 | FOUNDATION_EXPORT id HC_hasItems(id itemMatchers, ...) NS_REQUIRES_NIL_TERMINATION; 74 | 75 | #ifndef HC_DISABLE_SHORT_SYNTAX 76 | /*! 77 | * @abstract Creates a matcher for collections that matches when all specified matchers are 78 | * satisfied by any item in the examined collection. 79 | * @param itemMatchers... A comma-separated list of matchers ending with nil. 80 | * Any argument that is not a matcher is implicitly wrapped in an equalTo matcher to check 81 | * for equality. 82 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 83 | * performing one pass for each matcher. 84 | * 85 | * Example
86 | *
assertThat(\@[\@"foo", \@"bar", \@"baz"], hasItems(endsWith(\@"z"), endsWith(\@"o"), nil))
87 | * 88 | * Name Clash
89 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 90 | * HC_hasItems instead. 91 | */ 92 | #define hasItems(itemMatchers...) HC_hasItems(itemMatchers) 93 | #endif 94 | 95 | NS_ASSUME_NONNULL_END 96 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsCollectionContainingInAnyOrder.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if every item in a collection, in any order, satisfy a list of nested matchers. 11 | */ 12 | @interface HCIsCollectionContainingInAnyOrder : HCDiagnosingMatcher 13 | 14 | - (instancetype)initWithMatchers:(NSArray> *)itemMatchers NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_containsInAnyOrderIn(NSArray *itemMatchers); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates an order-agnostic matcher for collections that matches when each item in the 25 | * examined collection satisfies one matcher anywhere in the specified list of matchers. 26 | * @param itemMatchers An array of matchers. Any element that is not a matcher is implicitly wrapped 27 | * in an equalTo matcher to check for equality. 28 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 29 | * performing a single pass. For a positive match, the examined collection must be of the same 30 | * length as the specified list of matchers. 31 | * 32 | * Note: Each matcher in the specified list will only be used once during a given examination, so 33 | * be careful when specifying matchers that may be satisfied by more than one entry in an examined 34 | * collection. 35 | * 36 | * Examples
37 | *
assertThat(\@[\@"foo", \@"bar"], containsInAnyOrderIn(\@[equalTo(\@"bar"), equalTo(\@"foo")]))
38 | *
assertThat(\@[\@"foo", \@"bar"], containsInAnyOrderIn(@[\@"bar", \@"foo"]))
39 | * 40 | * Name Clash
41 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 42 | * HC_containsInAnyOrderIn instead. 43 | */ 44 | static inline id containsInAnyOrderIn(NSArray *itemMatchers) 45 | { 46 | return HC_containsInAnyOrderIn(itemMatchers); 47 | } 48 | #endif 49 | 50 | 51 | FOUNDATION_EXPORT id HC_containsInAnyOrder(id itemMatchers, ...) NS_REQUIRES_NIL_TERMINATION; 52 | 53 | #ifndef HC_DISABLE_SHORT_SYNTAX 54 | /*! 55 | * @abstract Creates an order-agnostic matcher for collections that matches when each item in the 56 | * examined collection satisfies one matcher anywhere in the specified list of matchers. 57 | * @param itemMatchers... A comma-separated list of matchers ending with nil. 58 | * Any argument that is not a matcher is implicitly wrapped in an equalTo matcher to check 59 | * for equality. 60 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 61 | * performing a single pass. For a positive match, the examined collection must be of the same 62 | * length as the specified list of matchers. 63 | * 64 | * Note: Each matcher in the specified list will only be used once during a given examination, so 65 | * be careful when specifying matchers that may be satisfied by more than one entry in an examined 66 | * collection. 67 | * 68 | * Examples
69 | *
assertThat(\@[\@"foo", \@"bar"], containsInAnyOrder(equalTo(\@"bar"), equalTo(\@"foo"), nil))
70 | *
assertThat(\@[\@"foo", \@"bar"], containsInAnyOrder(\@"bar", \@"foo", nil))
71 | * 72 | * Name Clash
73 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 74 | * HC_containsInAnyOrder instead. 75 | */ 76 | #define containsInAnyOrder(itemMatchers...) HC_containsInAnyOrder(itemMatchers) 77 | #endif 78 | 79 | NS_ASSUME_NONNULL_END 80 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsCollectionContainingInOrder.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if every item in a collection satisfies a list of nested matchers, in order. 11 | */ 12 | @interface HCIsCollectionContainingInOrder : HCDiagnosingMatcher 13 | 14 | - (instancetype)initWithMatchers:(NSArray> *)itemMatchers NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_containsIn(NSArray *itemMatchers); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher for collections that matches when each item in the examined 25 | * collection satisfies the corresponding matcher in the specified list of matchers. 26 | * @param itemMatchers An array of matchers. Any element that is not a matcher is implicitly wrapped 27 | * in an equalTo matcher to check for equality. 28 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 29 | * performing a single pass. For a positive match, the examined collection must be of the same 30 | * length as the specified list of matchers. 31 | * 32 | * Examples
33 | *
assertThat(\@[\@"foo", \@"bar"], containsIn(\@[equalTo(\@"foo"), equalTo(\@"bar")]))
34 | *
assertThat(\@[\@"foo", \@"bar"], containsIn(\@[\@"foo", \@"bar"]))
35 | * 36 | * Name Clash
37 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 38 | * HC_containsIn instead.) 39 | */ 40 | static inline id containsIn(NSArray *itemMatchers) 41 | { 42 | return HC_containsIn(itemMatchers); 43 | } 44 | #endif 45 | 46 | 47 | FOUNDATION_EXPORT id HC_contains(id itemMatchers, ...) NS_REQUIRES_NIL_TERMINATION; 48 | 49 | #ifndef HC_DISABLE_SHORT_SYNTAX 50 | /*! 51 | * @abstract Creates a matcher for collections that matches when each item in the examined 52 | * collection satisfies the corresponding matcher in the specified list of matchers. 53 | * @param itemMatchers... A comma-separated list of matchers ending with nil. 54 | * Any argument that is not a matcher is implicitly wrapped in an equalTo matcher to check 55 | * for equality. 56 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 57 | * performing a single pass. For a positive match, the examined collection must be of the same 58 | * length as the specified list of matchers. 59 | * 60 | * Examples
61 | *
assertThat(\@[\@"foo", \@"bar"], contains(equalTo(\@"foo"), equalTo(\@"bar"), nil))
62 | *
assertThat(\@[\@"foo", \@"bar"], contains(\@"foo", \@"bar", nil))
63 | * 64 | * Name Clash
65 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 66 | * HC_contains instead.) 67 | */ 68 | #define contains(itemMatchers...) HC_contains(itemMatchers) 69 | #endif 70 | 71 | NS_ASSUME_NONNULL_END 72 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsCollectionContainingInRelativeOrder.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if every item in a collection satisfies a list of nested matchers, in order. 11 | */ 12 | @interface HCIsCollectionContainingInRelativeOrder : HCDiagnosingMatcher 13 | 14 | - (instancetype)initWithMatchers:(NSArray> *)itemMatchers NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_containsInRelativeOrder(NSArray *itemMatchers); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher for collections that matches when the examined collection contains 25 | * items satisfying the specified list of matchers, in the same relative order. 26 | * @param itemMatchers Array of matchers that must be satisfied by the items provided by the 27 | * examined collection in the same relative order. 28 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 29 | * performing a single pass. 30 | * 31 | * Any element of itemMatchers that is not a matcher is implicitly wrapped in an 32 | * equalTo matcher to check for equality. 33 | * 34 | * Examples
35 | *
assertThat(\@[\@1, \@2, \@3, \@4, \@5], containsInRelativeOrder(equalTo(\@2), equalTo(\@4)))
36 | *
assertThat(\@[\@1, \@2, \@3, \@4, \@5], containsInRelativeOrder(\@2, \@4))
37 | * 38 | * Name Clash
39 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 40 | * HC_containsInRelativeOrder instead. 41 | */ 42 | static inline id containsInRelativeOrder(NSArray *itemMatchers) 43 | { 44 | return HC_containsInRelativeOrder(itemMatchers); 45 | } 46 | #endif 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsCollectionOnlyContaining.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if every item in a collection satisfies any of the nested matchers. 11 | */ 12 | @interface HCIsCollectionOnlyContaining : HCEvery 13 | @end 14 | 15 | FOUNDATION_EXPORT id HC_onlyContainsIn(NSArray *itemMatchers); 16 | 17 | #ifndef HC_DISABLE_SHORT_SYNTAX 18 | /*! 19 | * @abstract Creates a matcher for collections that matches when each item of the examined 20 | * collection satisfies any of the specified matchers. 21 | * @param itemMatchers An array of matchers. Any element that is not a matcher is implicitly wrapped 22 | * in an equalTo matcher to check for equality. 23 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 24 | * performing a single pass. Any matcher may match multiple elements. 25 | * 26 | * Example
27 | *
assertThat(\@[\@"Jon", \@"John", \@"Bob"], onlyContainsIn(\@[startsWith(\@"Jo"), startsWith(\@("Bo")]))
28 | * 29 | * Name Clash
30 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 31 | * HC_onlyContainsIn instead. 32 | */ 33 | static inline id onlyContainsIn(NSArray *itemMatchers) 34 | { 35 | return HC_onlyContainsIn(itemMatchers); 36 | } 37 | #endif 38 | 39 | 40 | FOUNDATION_EXPORT id HC_onlyContains(id itemMatchers, ...) NS_REQUIRES_NIL_TERMINATION; 41 | 42 | #ifndef HC_DISABLE_SHORT_SYNTAX 43 | /*! 44 | * @abstract Creates a matcher for collections that matches when each item of the examined 45 | * collection satisfies any of the specified matchers. 46 | * @param itemMatchers... A comma-separated list of matchers ending with nil. 47 | * Any argument that is not a matcher is implicitly wrapped in an equalTo matcher to check for 48 | * equality. 49 | * @discussion This matcher works on any collection that conforms to the NSFastEnumeration protocol, 50 | * performing a single pass. Any matcher may match multiple elements. 51 | * 52 | * Example
53 | *
assertThat(\@[\@"Jon", \@"John", \@"Bob"], onlyContains(startsWith(\@"Jo"), startsWith(\@("Bo"), nil))
54 | * 55 | * Name Clash
56 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 57 | * HC_onlyContains instead. 58 | */ 59 | #define onlyContains(itemMatchers...) HC_onlyContains(itemMatchers) 60 | #endif 61 | 62 | NS_ASSUME_NONNULL_END 63 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsDictionaryContaining.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if any entry in a dictionary satisfies the nested pair of matchers. 11 | */ 12 | @interface HCIsDictionaryContaining : HCBaseMatcher 13 | 14 | - (instancetype)initWithKeyMatcher:(id )keyMatcher 15 | valueMatcher:(id )valueMatcher NS_DESIGNATED_INITIALIZER; 16 | - (instancetype)init NS_UNAVAILABLE; 17 | 18 | @end 19 | 20 | 21 | FOUNDATION_EXPORT id HC_hasEntry(id keyMatcher, id valueMatcher); 22 | 23 | #ifndef HC_DISABLE_SHORT_SYNTAX 24 | /*! 25 | * @abstract Creates a matcher for NSDictionaries that matches when the examined dictionary contains 26 | * at least one entry whose key satisfies the specified keyMatcher and whose 27 | * value satisfies the specified valueMatcher. 28 | * @param keyMatcher The matcher to satisfy for the key, or an expected value for equalTo matching. 29 | * @param valueMatcher The matcher to satisfy for the value, or an expected value for equalTo matching. 30 | * @discussion Any argument that is not a matcher is implicitly wrapped in an equalTo 31 | * matcher to check for equality. 32 | * 33 | * Examples
34 | *
assertThat(myDictionary, hasEntry(equalTo(\@"foo"), equalTo(\@"bar")))
35 | *
assertThat(myDictionary, hasEntry(\@"foo", \@"bar"))
36 | * 37 | * Name Clash
38 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 39 | * HC_hasEntry instead. 40 | */ 41 | static inline id hasEntry(id keyMatcher, id valueMatcher) 42 | { 43 | return HC_hasEntry(keyMatcher, valueMatcher); 44 | } 45 | #endif 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsDictionaryContainingEntries.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if dictionary contains entries that satisfy the list of keys and value 11 | * matchers. 12 | */ 13 | @interface HCIsDictionaryContainingEntries : HCDiagnosingMatcher 14 | 15 | - (instancetype)initWithKeys:(NSArray *)keys 16 | valueMatchers:(NSArray> *)valueMatchers NS_DESIGNATED_INITIALIZER; 17 | - (instancetype)init NS_UNAVAILABLE; 18 | 19 | @end 20 | 21 | FOUNDATION_EXPORT id HC_hasEntriesIn(NSDictionary *valueMatchersForKeys); 22 | 23 | #ifndef HC_DISABLE_SHORT_SYNTAX 24 | /*! 25 | * @abstract Creates a matcher for NSDictionaries that matches when the examined dictionary contains 26 | * entries satisfying a dictionary of keys and their value matchers. 27 | * @param valueMatchersForKeys A dictionary of keys (not matchers) and their value matchers. Any 28 | * value argument that is not a matcher is implicitly wrapped in an equalTo matcher to 29 | * check for equality. 30 | * @discussion 31 | * Examples
32 | *
assertThat(personDict, hasEntriesIn(\@{\@"firstName": equalTo(\@"Jon"), \@"lastName": equalTo(\@"Reid")}))
33 | *
assertThat(personDict, hasEntriesIn(\@{\@"firstName": \@"Jon", \@"lastName": \@"Reid"}))
34 | * 35 | * Name Clash
36 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 37 | * HC_hasEntryIn instead. 38 | */ 39 | static inline id hasEntriesIn(NSDictionary *valueMatchersForKeys) 40 | { 41 | return HC_hasEntriesIn(valueMatchersForKeys); 42 | } 43 | #endif 44 | 45 | FOUNDATION_EXPORT id HC_hasEntries(id keysAndValueMatchers, ...) NS_REQUIRES_NIL_TERMINATION; 46 | 47 | #ifndef HC_DISABLE_SHORT_SYNTAX 48 | /*! 49 | * @abstract Creates a matcher for NSDictionaries that matches when the examined dictionary contains 50 | * entries satisfying a list of alternating keys and their value matchers. 51 | * @param keysAndValueMatchers... A key (not a matcher) to look up, followed by a value matcher or 52 | * an expected value for equalTo matching, in a comma-separated list ending 53 | * with nil 54 | * @discussion Note that the keys must be actual keys, not matchers. Any value argument that is not 55 | * a matcher is implicitly wrapped in an equalTo matcher to check for equality. 56 | * 57 | * Examples
58 | *
assertThat(personDict, hasEntries(\@"firstName", equalTo(\@"Jon"), \@"lastName", equalTo(\@"Reid"), nil))
59 | *
assertThat(personDict, hasEntries(\@"firstName", \@"Jon", \@"lastName", \@"Reid", nil))
60 | * 61 | * Name Clash
62 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 63 | * HC_hasEntry instead. 64 | */ 65 | #define hasEntries(keysAndValueMatchers...) HC_hasEntries(keysAndValueMatchers) 66 | #endif 67 | 68 | NS_ASSUME_NONNULL_END 69 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsDictionaryContainingKey.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if any entry in a dictionary has a key satisfying the nested matcher. 11 | */ 12 | @interface HCIsDictionaryContainingKey : HCBaseMatcher 13 | 14 | - (instancetype)initWithKeyMatcher:(id )keyMatcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_hasKey(id keyMatcher); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher for NSDictionaries that matches when the examined dictionary contains 25 | * at least key that satisfies the specified matcher. 26 | * @param keyMatcher The matcher to satisfy for the key, or an expected value for equalTo matching. 27 | * @discussion Any argument that is not a matcher is implicitly wrapped in an equalTo 28 | * matcher to check for equality. 29 | * 30 | * Examples
31 | *
assertThat(myDictionary, hasEntry(equalTo(\@"foo")))
32 | *
assertThat(myDictionary, hasEntry(\@"foo"))
33 | * 34 | * Name Clash
35 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 36 | * HC_hasKey instead. 37 | */ 38 | static inline id hasKey(id keyMatcher) 39 | { 40 | return HC_hasKey(keyMatcher); 41 | } 42 | #endif 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsDictionaryContainingValue.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if any entry in a dictionary has a value satisfying the nested matcher. 11 | */ 12 | @interface HCIsDictionaryContainingValue : HCBaseMatcher 13 | 14 | - (instancetype)initWithValueMatcher:(id )valueMatcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_hasValue(id valueMatcher); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher for NSDictionaries that matches when the examined dictionary contains 25 | * at least value that satisfies the specified matcher. 26 | * @param valueMatcher The matcher to satisfy for the value, or an expected value for equalTo matching. 27 | * @discussion This matcher works on any collection that has an -allValues method. 28 | * 29 | * Any argument that is not a matcher is implicitly wrapped in an equalTo matcher to check 30 | * for equality. 31 | * 32 | * Examples
33 | *
assertThat(myDictionary, hasValue(equalTo(\@"bar")))
34 | *
assertThat(myDictionary, hasValue(\@"bar"))
35 | * 36 | * Name Clash
37 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 38 | * HC_hasValue instead. 39 | */ 40 | static inline id hasValue(id valueMatcher) 41 | { 42 | return HC_hasValue(valueMatcher); 43 | } 44 | #endif 45 | 46 | NS_ASSUME_NONNULL_END 47 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsEmptyCollection.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches empty collections. 11 | */ 12 | @interface HCIsEmptyCollection : HCHasCount 13 | 14 | - (instancetype)init; 15 | 16 | @end 17 | 18 | 19 | FOUNDATION_EXPORT id HC_isEmpty(void); 20 | 21 | #ifndef HC_DISABLE_SHORT_SYNTAX 22 | /*! 23 | * @abstract Creates a matcher that matches any examined object whose -count method 24 | * returns zero. 25 | * 26 | * Example
27 | *
assertThat(\@[], isEmpty())
28 | * 29 | * Name Clash
30 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 31 | * HC_isEmpty instead. 32 | */ 33 | static inline id isEmpty(void) 34 | { 35 | return HC_isEmpty(); 36 | } 37 | #endif 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsEqual.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Is the value equal to another value, as tested by the -isEqual: method? 11 | */ 12 | @interface HCIsEqual : HCBaseMatcher 13 | 14 | - (instancetype)initEqualTo:(nullable id)expectedValue NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_equalTo(_Nullable id operand); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that matches when the examined object is equal to the specified 25 | * object, as determined by calling the -isEqual: method on the examined object. 26 | * @param operand The object to compare against as the expected value. 27 | * @discussion If the specified operand is nil, then the created matcher will match if 28 | * the examined object itself is nil, or if the examined object's -isEqual: 29 | * method returns YES when passed a nil. 30 | * 31 | * Name Clash
32 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 33 | * HC_equalTo instead. 34 | */ 35 | static inline id equalTo(_Nullable id operand) 36 | { 37 | return HC_equalTo(operand); 38 | } 39 | #endif 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsEqualCompressingWhiteSpace.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Tests if a string is equal to another string, when whitespace differences are (mostly) ignored. 11 | */ 12 | @interface HCIsEqualCompressingWhiteSpace : HCBaseMatcher 13 | 14 | - (instancetype)initWithString:(NSString *)string NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_equalToCompressingWhiteSpace(NSString *expectedString); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher for NSStrings that matches when the examined string is equal to the 25 | * specified expected string, when whitespace differences are (mostly) ignored. 26 | * @param expectedString The expected value of matched strings. (Must not be nil.) 27 | * @discussion To be exact, the following whitespace rules are applied: 28 | *
    29 | *
  • all leading and trailing whitespace of both the expectedString and the examined string are ignored
  • 30 | *
  • any remaining whitespace, appearing within either string, is collapsed to a single space before comparison
  • 31 | *
32 | * 33 | * Example
34 | *
assertThat(\@"   my\tfoo  bar ", equalToCompressingWhiteSpace(\@" my  foo bar"))
35 | * 36 | * Name Clash
37 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 38 | * HC_equalToCompressingWhiteSpace instead. 39 | */ 40 | static inline id equalToCompressingWhiteSpace(NSString *expectedString) 41 | { 42 | return HC_equalToCompressingWhiteSpace(expectedString); 43 | } 44 | #endif 45 | 46 | NS_ASSUME_NONNULL_END 47 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsEqualIgnoringCase.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Tests if a string is equal to another string, regardless of the case. 11 | */ 12 | @interface HCIsEqualIgnoringCase : HCBaseMatcher 13 | 14 | - (instancetype)initWithString:(NSString *)string NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_equalToIgnoringCase(NSString *expectedString); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher for NSStrings that matches when the examined string is equal to the 25 | * specified expected string, ignoring case differences. 26 | * @param expectedString The expected value of matched strings. (Must not be nil.) 27 | * @discussion 28 | * Example
29 | *
assertThat(\@"Foo", equalToIgnoringCase(\@"FOO"))
30 | * 31 | * Name Clash
32 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 33 | * HC_equalToIgnoringCase instead. 34 | */ 35 | static inline id equalToIgnoringCase(NSString *expectedString) 36 | { 37 | return HC_equalToIgnoringCase(expectedString); 38 | } 39 | #endif 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsEqualToNumber.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | FOUNDATION_EXPORT id HC_equalToChar(char value); 10 | 11 | #ifndef HC_DISABLE_SHORT_SYNTAX 12 | /*! 13 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 14 | * from the specified char value. 15 | * @param value The char value from which to create an NSNumber. 16 | * @discussion Consider using equalTo(\@(value)) instead. 17 | * 18 | * Name Clash
19 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 20 | * HC_equalToChar instead. 21 | */ 22 | static inline id equalToChar(char value) 23 | { 24 | return HC_equalToChar(value); 25 | } 26 | #endif 27 | 28 | 29 | FOUNDATION_EXPORT id HC_equalToDouble(double value); 30 | 31 | #ifndef HC_DISABLE_SHORT_SYNTAX 32 | /*! 33 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 34 | * from the specified double value. 35 | * @param value The double value from which to create an NSNumber. 36 | * @discussion Consider using equalTo(\@(value)) instead. 37 | * 38 | * Name Clash
39 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 40 | * HC_equalToDouble instead. 41 | */ 42 | static inline id equalToDouble(double value) 43 | { 44 | return HC_equalToDouble(value); 45 | } 46 | #endif 47 | 48 | 49 | FOUNDATION_EXPORT id HC_equalToFloat(float value); 50 | 51 | #ifndef HC_DISABLE_SHORT_SYNTAX 52 | /*! 53 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 54 | * from the specified float value. 55 | * @param value The float value from which to create an NSNumber. 56 | * @discussion Consider using equalTo(\@(value)) instead. 57 | * 58 | * Name Clash
59 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 60 | * HC_equalToFloat instead. 61 | */ 62 | static inline id equalToFloat(float value) 63 | { 64 | return HC_equalToFloat(value); 65 | } 66 | #endif 67 | 68 | 69 | FOUNDATION_EXPORT id HC_equalToInt(int value); 70 | 71 | #ifndef HC_DISABLE_SHORT_SYNTAX 72 | /*! 73 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 74 | * from the specified int value. 75 | * @param value The int value from which to create an NSNumber. 76 | * @discussion Consider using equalTo(\@(value)) instead. 77 | * 78 | * Name Clash
79 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 80 | * HC_equalToInt instead. 81 | */ 82 | static inline id equalToInt(int value) 83 | { 84 | return HC_equalToInt(value); 85 | } 86 | #endif 87 | 88 | 89 | FOUNDATION_EXPORT id HC_equalToLong(long value); 90 | 91 | #ifndef HC_DISABLE_SHORT_SYNTAX 92 | /*! 93 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 94 | * from the specified long value. 95 | * @param value The long value from which to create an NSNumber. 96 | * @discussion Consider using equalTo(\@(value)) instead. 97 | * 98 | * Name Clash
99 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 100 | * HC_equalToLong instead. 101 | */ 102 | static inline id equalToLong(long value) 103 | { 104 | return HC_equalToLong(value); 105 | } 106 | #endif 107 | 108 | 109 | FOUNDATION_EXPORT id HC_equalToLongLong(long long value); 110 | 111 | #ifndef HC_DISABLE_SHORT_SYNTAX 112 | /*! 113 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 114 | * from the specified long long value. 115 | * @param value The long long value from which to create an NSNumber. 116 | * @discussion Consider using equalTo(\@(value)) instead. 117 | * 118 | * Name Clash
119 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 120 | * HC_equalToLongLong instead. 121 | */ 122 | static inline id equalToLongLong(long long value) 123 | { 124 | return HC_equalToLongLong(value); 125 | } 126 | #endif 127 | 128 | 129 | FOUNDATION_EXPORT id HC_equalToShort(short value); 130 | 131 | #ifndef HC_DISABLE_SHORT_SYNTAX 132 | /*! 133 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 134 | * from the specified short value. 135 | * @param value The short value from which to create an NSNumber. 136 | * @discussion Consider using equalTo(\@(value)) instead. 137 | * 138 | * Name Clash
139 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 140 | * HC_equalToShort instead. 141 | */ 142 | static inline id equalToShort(short value) 143 | { 144 | return HC_equalToShort(value); 145 | } 146 | #endif 147 | 148 | 149 | FOUNDATION_EXPORT id HC_equalToUnsignedChar(unsigned char value); 150 | 151 | #ifndef HC_DISABLE_SHORT_SYNTAX 152 | /*! 153 | * @abstract equalToUnsignedChar(value) - 154 | * Creates a matcher that matches when the examined object is equal to an NSNumber created from the 155 | * specified unsigned char value. 156 | * @param value The unsigned char value from which to create an NSNumber. 157 | * @discussion Consider using equalTo(\@(value)) instead. 158 | * 159 | * Name Clash
160 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 161 | * HC_equalToUnsignedChar instead. 162 | */ 163 | static inline id equalToUnsignedChar(unsigned char value) 164 | { 165 | return HC_equalToUnsignedChar(value); 166 | } 167 | #endif 168 | 169 | 170 | FOUNDATION_EXPORT id HC_equalToUnsignedInt(unsigned int value); 171 | 172 | #ifndef HC_DISABLE_SHORT_SYNTAX 173 | /*! 174 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 175 | * from the specified unsigned int value. 176 | * @param value The unsigned int value from which to create an NSNumber. 177 | * @discussion Consider using equalTo(\@(value)) instead. 178 | * 179 | * Name Clash
180 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 181 | * HC_equalToUnsignedInt instead. 182 | */ 183 | static inline id equalToUnsignedInt(unsigned int value) 184 | { 185 | return HC_equalToUnsignedInt(value); 186 | } 187 | #endif 188 | 189 | 190 | FOUNDATION_EXPORT id HC_equalToUnsignedLong(unsigned long value); 191 | 192 | #ifndef HC_DISABLE_SHORT_SYNTAX 193 | /*! 194 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 195 | * from the specified unsigned long value. 196 | * @param value The unsigned long value from which to create an NSNumber. 197 | * @discussion Consider using equalTo(\@(value)) instead. 198 | * 199 | * Name Clash
200 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 201 | * HC_equalToUnsignedLong instead. 202 | */ 203 | static inline id equalToUnsignedLong(unsigned long value) 204 | { 205 | return HC_equalToUnsignedLong(value); 206 | } 207 | #endif 208 | 209 | 210 | FOUNDATION_EXPORT id HC_equalToUnsignedLongLong(unsigned long long value); 211 | 212 | #ifndef HC_DISABLE_SHORT_SYNTAX 213 | /*! 214 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 215 | * from the specified unsigned long long value. 216 | * @param value The unsigned long long value from which to create an NSNumber. 217 | * @discussion Consider using equalTo(\@(value)) instead. 218 | * 219 | * Name Clash
220 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 221 | * HC_equalToUnsignedLongLong instead. 222 | */ 223 | static inline id equalToUnsignedLongLong(unsigned long long value) 224 | { 225 | return HC_equalToUnsignedLongLong(value); 226 | } 227 | #endif 228 | 229 | 230 | FOUNDATION_EXPORT id HC_equalToUnsignedShort(unsigned short value); 231 | 232 | #ifndef HC_DISABLE_SHORT_SYNTAX 233 | /*! 234 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 235 | * from the specified unsigned short value. 236 | * @param value The unsigned short value from which to create an NSNumber. 237 | * @discussion Consider using equalTo(\@(value)) instead. 238 | * 239 | * Name Clash
240 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 241 | * HC_equalToUnsignedShort instead. 242 | */ 243 | static inline id equalToUnsignedShort(unsigned short value) 244 | { 245 | return HC_equalToUnsignedShort(value); 246 | } 247 | #endif 248 | 249 | 250 | FOUNDATION_EXPORT id HC_equalToInteger(NSInteger value); 251 | 252 | #ifndef HC_DISABLE_SHORT_SYNTAX 253 | /*! 254 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 255 | * from the specified NSInteger value. 256 | * @param value The NSInteger value from which to create an NSNumber. 257 | * @discussion Consider using equalTo(\@(value)) instead. 258 | * 259 | * Name Clash
260 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 261 | * HC_equalToInteger instead. 262 | */ 263 | static inline id equalToInteger(NSInteger value) 264 | { 265 | return HC_equalToInteger(value); 266 | } 267 | #endif 268 | 269 | 270 | FOUNDATION_EXPORT id HC_equalToUnsignedInteger(NSUInteger value); 271 | 272 | #ifndef HC_DISABLE_SHORT_SYNTAX 273 | /*! 274 | * @abstract Creates a matcher that matches when the examined object is equal to an NSNumber created 275 | * from the specified NSUInteger value. 276 | * @param value The NSUInteger value from which to create an NSNumber. 277 | * @discussion Consider using equalTo(\@(value)) instead. 278 | * 279 | * Name Clash
280 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 281 | * HC_equalToUnsignedInteger instead. 282 | */ 283 | static inline id equalToUnsignedInteger(NSUInteger value) 284 | { 285 | return HC_equalToUnsignedInteger(value); 286 | } 287 | #endif 288 | 289 | NS_ASSUME_NONNULL_END 290 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsIn.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches if examined object is contained within the nested collection. 11 | */ 12 | @interface HCIsIn : HCBaseMatcher 13 | 14 | - (instancetype)initWithCollection:(id)collection NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_isIn(id aCollection); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that matches when the examined object is found within the specified 25 | * collection. 26 | * @param aCollection The collection to search. 27 | * @discussion Invokes -containsObject: on aCollection to determine if the 28 | * examined object is an element of the collection. 29 | * 30 | * Example
31 | *
assertThat(\@"foo", isIn(\@@[\@"bar", \@"foo"]))
32 | * 33 | * Name Clash
34 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 35 | * HC_isIn instead. 36 | */ 37 | static inline id isIn(id aCollection) 38 | { 39 | return HC_isIn(aCollection); 40 | } 41 | #endif 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsInstanceOf.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches objects that are of a given class or any subclass. 11 | */ 12 | @interface HCIsInstanceOf : HCClassMatcher 13 | @end 14 | 15 | 16 | FOUNDATION_EXPORT id HC_instanceOf(Class expectedClass); 17 | 18 | #ifndef HC_DISABLE_SHORT_SYNTAX 19 | /*! 20 | * @abstract Creates a matcher that matches when the examined object is an instance of, or inherits 21 | * from, the specified class. 22 | * @param expectedClass The class to compare against as the expected class. 23 | * @discussion 24 | * Example
25 | *
assertThat(canoe, instanceOf([Canoe class]))
26 | * 27 | * Name Clash
28 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 29 | * HC_instanceOf instead. 30 | */ 31 | static inline id instanceOf(Class expectedClass) 32 | { 33 | return HC_instanceOf(expectedClass); 34 | } 35 | #endif 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsNil.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Is the value nil? 11 | */ 12 | @interface HCIsNil : HCBaseMatcher 13 | @end 14 | 15 | 16 | FOUNDATION_EXPORT id HC_nilValue(void); 17 | 18 | #ifndef HC_DISABLE_SHORT_SYNTAX 19 | /*! 20 | * @abstract Creates a matcher that matches when the examined object is nil. 21 | * @discussion 22 | * Example
23 | *
assertThat(myObject, nilValue())
24 | * 25 | * Name Clash
26 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 27 | * HC_nilValue instead. 28 | */ 29 | static inline id nilValue(void) 30 | { 31 | return HC_nilValue(); 32 | } 33 | #endif 34 | 35 | 36 | FOUNDATION_EXPORT id HC_notNilValue(void); 37 | 38 | #ifndef HC_DISABLE_SHORT_SYNTAX 39 | /*! 40 | * @abstract Creates a matcher that matches when the examined object is not nil. 41 | * @discussion 42 | * Example
43 | *
assertThat(myObject, notNilValue())
44 | * 45 | * Name Clash
46 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 47 | * HC_notNilValue instead. 48 | */ 49 | static inline id notNilValue(void) 50 | { 51 | return HC_notNilValue(); 52 | } 53 | #endif 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsNot.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Calculates the logical negation of a matcher. 11 | */ 12 | @interface HCIsNot : HCBaseMatcher 13 | 14 | - (instancetype)initWithMatcher:(id )matcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_isNot(_Nullable id value); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that wraps an existing matcher, but inverts the logic by which it 25 | * will match. 26 | * @param value The matcher to negate, or an expected value to match for inequality. 27 | * @discussion If value is not a matcher, it is implicitly wrapped in an equalTo 28 | * matcher to check for equality, and thus matches for inequality. 29 | * 30 | * Examples
31 | *
assertThat(cheese, isNot(equalTo(smelly)))
32 | *
assertThat(cheese, isNot(smelly))
33 | * 34 | * Name Clash
35 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 36 | * HC_isNot instead. 37 | */ 38 | static inline id isNot(_Nullable id value) 39 | { 40 | return HC_isNot(value); 41 | } 42 | #endif 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsSame.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Is the value the same object as another value? 11 | */ 12 | @interface HCIsSame : HCBaseMatcher 13 | 14 | - (instancetype)initSameAs:(nullable id)object NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_sameInstance(_Nullable id expectedInstance); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that matches only when the examined object is the same instance as 25 | * the specified target object. 26 | * @param expectedInstance The expected instance. 27 | * @discussion 28 | * Example
29 | *
assertThat(delegate, sameInstance(expectedDelegate))
30 | * 31 | * Name Clash
32 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 33 | * HC_sameInstance instead. 34 | */ 35 | static inline id sameInstance(_Nullable id expectedInstance) 36 | { 37 | return HC_sameInstance(expectedInstance); 38 | } 39 | #endif 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsTrueFalse.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches true values. 11 | */ 12 | @interface HCIsTrue : HCBaseMatcher 13 | @end 14 | 15 | /*! 16 | * @abstract Matches false values. 17 | */ 18 | @interface HCIsFalse : HCBaseMatcher 19 | @end 20 | 21 | 22 | FOUNDATION_EXPORT id HC_isTrue(void); 23 | 24 | #ifndef HC_DISABLE_SHORT_SYNTAX 25 | /*! 26 | * @abstract Creates a matcher that matches when the examined object is an non-zero NSNumber. 27 | * @discussion 28 | * Name Clash
29 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 30 | * HC_isTrue instead. 31 | */ 32 | static inline id isTrue(void) 33 | { 34 | return HC_isTrue(); 35 | } 36 | #endif 37 | 38 | 39 | FOUNDATION_EXPORT id HC_isFalse(void); 40 | 41 | #ifndef HC_DISABLE_SHORT_SYNTAX 42 | /*! 43 | * @abstract Creates a matcher that matches when the examined object is NSNumber zero. 44 | * @discussion 45 | * Name Clash
46 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 47 | * HC_isFalse instead. 48 | */ 49 | static inline id isFalse(void) 50 | { 51 | return HC_isFalse(); 52 | } 53 | #endif 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCIsTypeOf.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches objects that are of a given class. 11 | */ 12 | @interface HCIsTypeOf : HCClassMatcher 13 | @end 14 | 15 | 16 | FOUNDATION_EXPORT id HC_isA(Class expectedClass); 17 | 18 | #ifndef HC_DISABLE_SHORT_SYNTAX 19 | /*! 20 | * @abstract Creates a matcher that matches when the examined object is an instance of the specified 21 | * class, but not of any subclass. 22 | * @param expectedClass The class to compare against as the expected class. 23 | * @discussion 24 | * Example
25 | *
assertThat(canoe, isA([Canoe class]))
26 | * 27 | * Name Clash
28 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 29 | * HC_isA instead. 30 | */ 31 | static inline id isA(Class expectedClass) 32 | { 33 | return HC_isA(expectedClass); 34 | } 35 | #endif 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCMatcher.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import "HCSelfDescribing.h" 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract A matcher over acceptable values. 11 | * @discussion A matcher is able to describe itself to give feedback when it fails. 12 | * 13 | * HCMatcher implementations should not directly implement this protocol. Instead, extend the 14 | * HCBaseMatcher class, which will ensure that the HCMatcher API can grow to support new features 15 | * and remain compatible with all HCMatcher implementations. 16 | */ 17 | @protocol HCMatcher 18 | 19 | /*! 20 | * @abstract Evaluates the matcher for argument item. 21 | * @param item The object against which the matcher is evaluated. 22 | * @return YES if item matches, otherwise NO. 23 | */ 24 | - (BOOL)matches:(nullable id)item; 25 | 26 | /*! 27 | * @abstract Evaluates the matcher for argument item. 28 | * @param item The object against which the matcher is evaluated. 29 | * @param mismatchDescription The description to be built or appended to if item does not match. 30 | * @return YES if item matches, otherwise NO. 31 | */ 32 | - (BOOL)matches:(nullable id)item describingMismatchTo:(nullable id )mismatchDescription; 33 | 34 | /*! 35 | * @abstract Generates a description of why the matcher has not accepted the item. 36 | * @param item The item that the HCMatcher has rejected. 37 | * @param mismatchDescription The description to be built or appended to. 38 | * @discussion The description will be part of a larger description of why a matching failed, so it 39 | * should be concise. 40 | * 41 | * This method assumes that matches:item is false, but will not check this. 42 | */ 43 | - (void)describeMismatchOf:(nullable id)item to:(nullable id )mismatchDescription; 44 | 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCOrderingComparison.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Matches values with -compare:. 11 | */ 12 | @interface HCOrderingComparison : HCBaseMatcher 13 | 14 | - (instancetype)initComparing:(id)expectedValue 15 | minCompare:(NSComparisonResult)min 16 | maxCompare:(NSComparisonResult)max 17 | comparisonDescription:(NSString *)comparisonDescription NS_DESIGNATED_INITIALIZER; 18 | - (instancetype)init NS_UNAVAILABLE; 19 | 20 | @end 21 | 22 | 23 | FOUNDATION_EXPORT id HC_greaterThan(id value); 24 | 25 | #ifndef HC_DISABLE_SHORT_SYNTAX 26 | /*! 27 | * @abstract Creates a matcher that matches when the examined object is greater than the specified 28 | * value, as reported by the -compare: method of the examined object. 29 | * @param value The value which, when passed to the -compare: method of the examined 30 | * object, should return NSOrderedAscending. 31 | * @discussion 32 | * Example
33 | *
assertThat(\@2, greaterThan(\@1))
34 | * 35 | * Name Clash
36 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 37 | * HC_greaterThan instead. 38 | */ 39 | static inline id greaterThan(id value) 40 | { 41 | return HC_greaterThan(value); 42 | } 43 | #endif 44 | 45 | 46 | FOUNDATION_EXPORT id HC_greaterThanOrEqualTo(id value); 47 | 48 | #ifndef HC_DISABLE_SHORT_SYNTAX 49 | /*! 50 | * @abstract Creates a matcher that matches when the examined object is greater than or equal to the 51 | * specified value, as reported by the -compare: method of the examined object. 52 | * @param value The value which, when passed to the -compare: method of the examined 53 | * object, should return NSOrderedAscending or NSOrderedSame. 54 | * @discussion 55 | * Example
56 | *
assertThat(\@1, greaterThanOrEqualTo(\@1))
57 | * 58 | * Name Clash
59 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 60 | * HC_greaterThanOrEqualTo instead. 61 | */ 62 | static inline id greaterThanOrEqualTo(id value) 63 | { 64 | return HC_greaterThanOrEqualTo(value); 65 | } 66 | #endif 67 | 68 | 69 | FOUNDATION_EXPORT id HC_lessThan(id value); 70 | 71 | #ifndef HC_DISABLE_SHORT_SYNTAX 72 | /*! 73 | * @abstract Creates a matcher that matches when the examined object is less than the specified 74 | * value, as reported by the -compare: method of the examined object. 75 | * @param value The value which, when passed to the -compare: method of the examined 76 | * object, should return NSOrderedDescending. 77 | * @discussion 78 | * Example
79 | *
assertThat(\@1, lessThan(\@2))
80 | * 81 | * Name Clash
82 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 83 | * HC_lessThan instead. 84 | */ 85 | static inline id lessThan(id value) 86 | { 87 | return HC_lessThan(value); 88 | } 89 | #endif 90 | 91 | 92 | FOUNDATION_EXPORT id HC_lessThanOrEqualTo(id value); 93 | 94 | #ifndef HC_DISABLE_SHORT_SYNTAX 95 | /*! 96 | * @abstract Creates a matcher that matches when the examined object is less than or equal to the 97 | * specified value, as reported by the -compare: method of the examined object. 98 | * @param value The value which, when passed to the -compare: method of the examined 99 | * object, should return NSOrderedDescending or NSOrderedSame. 100 | * @discussion 101 | * Example
102 | *
assertThat(\@1, lessThanOrEqualTo(\@1))
103 | * 104 | * Name Clash
105 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 106 | * HC_lessThanOrEqualTo instead. 107 | */ 108 | static inline id lessThanOrEqualTo(id value) 109 | { 110 | return HC_lessThanOrEqualTo(value); 111 | } 112 | #endif 113 | 114 | NS_ASSUME_NONNULL_END 115 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCRequireNonNilObject.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Throws an NSException if obj is nil. 11 | */ 12 | FOUNDATION_EXPORT void HCRequireNonNilObject(id obj); 13 | 14 | NS_ASSUME_NONNULL_END 15 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCSelfDescribing.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | #import "HCDescription.h" // Convenience header 7 | 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | /*! 12 | * @abstract The ability of an object to describe itself. 13 | */ 14 | @protocol HCSelfDescribing 15 | 16 | /*! 17 | * @abstract Generates a description of the object. 18 | * @param description The description to be built or appended to. 19 | * @discussion The description may be part of a description of a larger object of which this is just 20 | * a component, so it should be worded appropriately. 21 | */ 22 | - (void)describeTo:(id )description; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCStringContains.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Tests if string that contains a substring. 11 | */ 12 | @interface HCStringContains : HCSubstringMatcher 13 | @end 14 | 15 | 16 | FOUNDATION_EXPORT id HC_containsSubstring(NSString *substring); 17 | 18 | #ifndef HC_DISABLE_SHORT_SYNTAX 19 | /*! 20 | * @abstract Creates a matcher that matches when the examined object is a string containing the 21 | * specified substring anywhere. 22 | * @param substring The string to search for. (Must not be nil.) 23 | * @discussion The matcher invokes -rangeOfString: on the examined object, passing the 24 | * specified substring and matching if it is found. 25 | * 26 | * Example
27 | *
assertThat(\@"myStringOfNote", containsSubstring(\@"ring"))
28 | * 29 | * Name Clash
30 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 31 | * HC_containsSubstring instead. 32 | */ 33 | static inline id containsSubstring(NSString *substring) 34 | { 35 | return HC_containsSubstring(substring); 36 | } 37 | #endif 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCStringContainsInOrder.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Tests if string that contains a list of substrings in relative order. 11 | */ 12 | @interface HCStringContainsInOrder : HCBaseMatcher 13 | 14 | - (instancetype)initWithSubstrings:(NSArray *)substrings NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_stringContainsInOrderIn(NSArray *substrings); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates matcher for NSStrings that matches when the examined string contains all of the 25 | * specified substrings, considering the order of their appearance. 26 | * @param substrings An array of strings. 27 | * @discussion 28 | * Example
29 | *
assertThat(\@"myfoobarbaz", stringContainsInOrderIn(\@[\@"bar", \@"foo"]))
30 | * fails as "foo" occurs before "bar" in the string "myfoobarbaz" 31 | * 32 | * Name Clash
33 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 34 | * HC_stringContainsInOrderIn instead. 35 | */ 36 | static inline id stringContainsInOrderIn(NSArray *substrings) 37 | { 38 | return HC_stringContainsInOrderIn(substrings); 39 | } 40 | #endif 41 | 42 | 43 | FOUNDATION_EXPORT id HC_stringContainsInOrder(NSString *substrings, ...) NS_REQUIRES_NIL_TERMINATION; 44 | 45 | #ifndef HC_DISABLE_SHORT_SYNTAX 46 | /*! 47 | * @abstract Creates matcher for NSStrings that matches when the examined string contains all of the 48 | * specified substrings, considering the order of their appearance. 49 | * @param substrings... A comma-separated list of strings, ending with nil. 50 | * @discussion 51 | * Example
52 | *
assertThat(\@"myfoobarbaz", stringContainsInOrder(\@"bar", \@"foo", nil))
53 | * fails as "foo" occurs before "bar" in the string "myfoobarbaz" 54 | * 55 | * Name Clash
56 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 57 | * HC_stringContainsInOrder instead. 58 | */ 59 | #define stringContainsInOrder(substrings...) HC_stringContainsInOrder(substrings) 60 | #endif 61 | 62 | NS_ASSUME_NONNULL_END 63 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCStringDescription.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | @protocol HCSelfDescribing; 7 | 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | /*! 12 | * @abstract An HCDescription that is stored as a string. 13 | */ 14 | @interface HCStringDescription : HCBaseDescription 15 | 16 | 17 | /*! 18 | * @abstract Returns the description of an HCSelfDescribing object as a string. 19 | * @param selfDescribing The object to be described. 20 | * @return The description of the object. 21 | */ 22 | + (NSString *)stringFrom:(id )selfDescribing; 23 | 24 | /*! 25 | * @abstract Creates and returns an empty description. 26 | */ 27 | + (instancetype)stringDescription; 28 | 29 | /*! 30 | * @abstract Initializes a newly allocated HCStringDescription that is initially empty. 31 | */ 32 | - (instancetype)init NS_DESIGNATED_INITIALIZER; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCStringEndsWith.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Tests if string ends with a substring. 11 | */ 12 | @interface HCStringEndsWith : HCSubstringMatcher 13 | @end 14 | 15 | 16 | FOUNDATION_EXPORT id HC_endsWith(NSString *suffix); 17 | 18 | #ifndef HC_DISABLE_SHORT_SYNTAX 19 | /*! 20 | * @abstract Creates a matcher that matches when the examined object is a string that ends with the 21 | * specified string. 22 | * @param suffix The substring that the returned matcher will expect at the end of any examined 23 | * string. (Must not be nil.) 24 | * @discussion The matcher invokes -hasSuffix: on the examined object, passing the 25 | * specified suffix. 26 | * 27 | * Example
28 | *
assertThat(\@"myStringOfNote", endsWith(\@"Note"))
29 | * 30 | * Name Clash
31 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 32 | * HC_endsWith instead. 33 | */ 34 | static inline id endsWith(NSString *suffix) 35 | { 36 | return HC_endsWith(suffix); 37 | } 38 | #endif 39 | 40 | NS_ASSUME_NONNULL_END 41 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCStringStartsWith.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Tests string starts with a substring. 11 | */ 12 | @interface HCStringStartsWith : HCSubstringMatcher 13 | @end 14 | 15 | 16 | FOUNDATION_EXPORT id HC_startsWith(NSString *prefix); 17 | 18 | #ifndef HC_DISABLE_SHORT_SYNTAX 19 | /*! 20 | * @abstract Creates a matcher that matches when the examined object is a string that starts with 21 | * the specified string. 22 | * @param prefix The substring that the returned matcher will expect at the start of any examined 23 | * string. (Must not be nil.) 24 | * @discussion The matcher invokes -hasPrefix: on the examined object, passing the 25 | * specified prefix. 26 | * 27 | * Example
28 | *
assertThat(\@"myStringOfNote", startsWith(\@"my"))
29 | * 30 | * Name Clash
31 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 32 | * HC_startsWith instead. 33 | */ 34 | static inline id startsWith(NSString *prefix) 35 | { 36 | return HC_startsWith(prefix); 37 | } 38 | #endif 39 | 40 | NS_ASSUME_NONNULL_END 41 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCSubstringMatcher.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface HCSubstringMatcher : HCBaseMatcher 10 | 11 | @property (nonatomic, copy, readonly) NSString *substring; 12 | 13 | - (instancetype)initWithSubstring:(NSString *)substring NS_DESIGNATED_INITIALIZER; 14 | - (instancetype)init NS_UNAVAILABLE; 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCTestFailure.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | @abstract Test failure location and reason. 11 | */ 12 | @interface HCTestFailure : NSObject 13 | 14 | /*! 15 | * @abstract Test case used to run test method. 16 | * @discussion Can be nil. 17 | * 18 | * For unmet OCHamcrest assertions, if the assertion was assertThat or 19 | * assertWithTimeout, testCase will be the test case instance. 20 | */ 21 | @property (nonatomic, strong, readonly) id testCase; 22 | 23 | /*! @abstract File name to report. */ 24 | @property (nonatomic, copy, readonly) NSString *fileName; 25 | 26 | /*! @abstract Line number to report. */ 27 | @property (nonatomic, assign, readonly) NSUInteger lineNumber; 28 | 29 | /*! @abstract Failure reason to report. */ 30 | @property (nonatomic, strong, readonly) NSString *reason; 31 | 32 | /*! 33 | * @abstract Initializes a newly allocated instance of a test failure. 34 | */ 35 | - (instancetype)initWithTestCase:(id)testCase 36 | fileName:(NSString *)fileName 37 | lineNumber:(NSUInteger)lineNumber 38 | reason:(NSString *)reason; 39 | 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCTestFailureReporter.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | @class HCTestFailure; 7 | 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | /*! 12 | Chain-of-responsibility for handling test failures. 13 | */ 14 | @interface HCTestFailureReporter : NSObject 15 | 16 | @property (nullable, nonatomic, strong) HCTestFailureReporter *successor; 17 | 18 | /*! 19 | Handle test failure at specific location, or pass to successor. 20 | */ 21 | - (void)handleFailure:(HCTestFailure *)failure; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCTestFailureReporterChain.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | @class HCTestFailureReporter; 7 | 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | /*! 12 | * @abstract Manage chain-of-responsibility for reporting test failures. 13 | * @discussion This provides a generic way of reporting test failures without knowing about the 14 | * underlying test framework. By default, we try XCTest first, then SenTestingKit. If we run out of 15 | * options, the final catch-all is to throw an NSException describing the test failure. 16 | */ 17 | @interface HCTestFailureReporterChain : NSObject 18 | 19 | /*! 20 | * @abstract Returns current chain of test failure reporters. 21 | */ 22 | + (HCTestFailureReporter *)reporterChain; 23 | 24 | /*! 25 | * @abstract Adds specified test failure reporter to head of chain-of-responsibility. 26 | */ 27 | + (void)addReporter:(HCTestFailureReporter *)reporter; 28 | 29 | /*! 30 | * @abstract Resets chain-of-responsibility to default. 31 | */ 32 | + (void)reset; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCThrowsException.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Does executing a block throw an exception which satisfies a nested matcher? 11 | */ 12 | @interface HCThrowsException : HCDiagnosingMatcher 13 | 14 | - (id)initWithExceptionMatcher:(id)exceptionMatcher NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | 20 | FOUNDATION_EXPORT id HC_throwsException(id exceptionMatcher); 21 | 22 | #ifndef HC_DISABLE_SHORT_SYNTAX 23 | /*! 24 | * @abstract Creates a matcher that matches when the examined object is a block which, when 25 | * executed, throws an exception satisfying the specified matcher. 26 | * @param exceptionMatcher The matcher to satisfy when passed the exception. 27 | * @discussion 28 | * Example
29 | *
assertThat(^{ [obj somethingBad]; }, throwsException(hasProperty(@"reason", @"EXPECTED REASON")))
30 | * 31 | * Name Clash
32 | * In the event of a name clash, #define HC_DISABLE_SHORT_SYNTAX and use the synonym 33 | * HC_throwsException instead. 34 | */ 35 | static inline id throwsException(id exceptionMatcher) 36 | { 37 | return HC_throwsException(exceptionMatcher); 38 | } 39 | #endif 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/HCWrapInMatcher.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | @protocol HCMatcher; 7 | 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | /*! 12 | * @abstract Wraps argument in a matcher, if necessary. 13 | * @return The argument as-is if it is already a matcher, otherwise wrapped in an equalTo matcher. 14 | */ 15 | FOUNDATION_EXPORT _Nullable id HCWrapInMatcher(_Nullable id matcherOrValue); 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Headers/OCHamcrest.h: -------------------------------------------------------------------------------- 1 | // OCHamcrest by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 hamcrest.org. See LICENSE.txt 3 | 4 | #import 5 | 6 | FOUNDATION_EXPORT double OCHamcrestVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char OCHamcrestVersionString[]; 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | #import 38 | #import 39 | #import 40 | #import 41 | #import 42 | #import 43 | #import 44 | #import 45 | #import 46 | #import 47 | #import 48 | #import 49 | #import 50 | #import 51 | #import 52 | #import 53 | 54 | // Carthage workaround: Include transitive public headers 55 | #import 56 | #import 57 | #import 58 | #import 59 | #import 60 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module OCHamcrest { 2 | umbrella header "OCHamcrest.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/OCHamcrest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewchidden/btt-services/eaf4f5bb711c900ec0bc1fe6c16f9dd40c75f877/Tests/Frameworks/OCHamcrest.framework/Versions/A/OCHamcrest -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 17E202 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | OCHamcrest 11 | CFBundleIdentifier 12 | org.hamcrest.OCHamcrest 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | OCHamcrest 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 7.1.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleSupportedPlatforms 24 | 25 | MacOSX 26 | 27 | CFBundleVersion 28 | 7.1.1 29 | DTCompiler 30 | com.apple.compilers.llvm.clang.1_0 31 | DTPlatformBuild 32 | 9E145 33 | DTPlatformVersion 34 | GM 35 | DTSDKBuild 36 | 17E189 37 | DTSDKName 38 | macosx10.13 39 | DTXcode 40 | 0930 41 | DTXcodeBuild 42 | 9E145 43 | NSHumanReadableCopyright 44 | Copyright © 2018 hamcrest.org 45 | 46 | 47 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCHamcrest.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Modules: -------------------------------------------------------------------------------- 1 | Versions/Current/Modules -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/OCMockito: -------------------------------------------------------------------------------- 1 | Versions/Current/OCMockito -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/MKTBaseMockObject.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | 4 | #import 5 | #import "MKTNonObjectArgumentMatching.h" 6 | 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | @interface MKTBaseMockObject : NSProxy 11 | 12 | + (BOOL)isMockObject:(id)object; 13 | 14 | - (instancetype)init; 15 | - (void)stopMocking; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/MKTClassObjectMock.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | // Contribution by David Hart 4 | 5 | #import "MKTBaseMockObject.h" 6 | 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | /*! 11 | * @abstract Mock object of a given class object. 12 | */ 13 | @interface MKTClassObjectMock : MKTBaseMockObject 14 | 15 | @property (nonatomic, strong, readonly) Class mockedClass; 16 | 17 | - (instancetype)initWithClass:(Class)aClass NS_DESIGNATED_INITIALIZER; 18 | - (instancetype)init NS_UNAVAILABLE; 19 | - (void)swizzleSingletonAtSelector:(SEL)singletonSelector; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/MKTNonObjectArgumentMatching.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | 4 | @protocol HCMatcher; 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Ability to specify OCHamcrest matchers for non-object arguments. 11 | */ 12 | @protocol MKTNonObjectArgumentMatching 13 | 14 | /*! 15 | * @abstract Specifies OCHamcrest matcher for a specific argument of a method. 16 | * @discussion For methods arguments that take objects, just pass the matcher directly as a method 17 | * call. But for arguments that take non-objects, pass in a dummy value to satisfy the compiler, but 18 | * call this to override it with the given matcher. Upon verification, the actual argument received 19 | * will be converted to an object before being checked by the matcher. 20 | * 21 | * The argument index is 0-based, so the first argument of a method has index 0. 22 | * 23 | * Examples: 24 | *
[[given([mockFetchedResultsController performFetch:NULL]) withMatcher:anything()] willReturn:\@YES];
25 | * This stubs performFetch: to return YES for any NSError ** argument. 26 | * 27 | *
[[verify(mockArray) withMatcher:greaterThan(@5]) forArgument:0] removeObjectAtIndex:0];
28 | * This verifies that removeObjectAtIndex: was called with an index greater than 5. 29 | */ 30 | - (id)withMatcher:(id )matcher forArgument:(NSUInteger)index; 31 | 32 | /*! 33 | * @abstract Specifies OCHamcrest matcher for the first argument of a method. 34 | * @discussion Equivalent to withMatcher:matcher forArgument:0. 35 | * 36 | * Example: 37 | *
[[verify(mockArray) withMatcher:greaterThan(\@5)] removeObjectAtIndex:0];
38 | * This verifies that removeObjectAtIndex: was called with an index greater than 5. 39 | */ 40 | - (id)withMatcher:(id )matcher; 41 | 42 | @end 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/MKTObjectAndProtocolMock.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | // Contribution by Kevin Lundberg 4 | 5 | #import "MKTProtocolMock.h" 6 | 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | /*! 11 | * @abstract Mock object of a given class that also implements a given protocol. 12 | */ 13 | @interface MKTObjectAndProtocolMock : MKTProtocolMock 14 | 15 | - (instancetype)initWithClass:(Class)aClass protocol:(Protocol *)protocol NS_DESIGNATED_INITIALIZER; 16 | - (instancetype)initWithProtocol:(Protocol *)aProtocol 17 | includeOptionalMethods:(BOOL)includeOptionalMethods NS_UNAVAILABLE; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/MKTObjectMock.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | 4 | #import "MKTBaseMockObject.h" 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Mock object of a given class. 11 | */ 12 | @interface MKTObjectMock : MKTBaseMockObject 13 | 14 | - (instancetype)initWithClass:(Class)aClass NS_DESIGNATED_INITIALIZER; 15 | - (instancetype)init NS_UNAVAILABLE; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/MKTOngoingStubbing.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | 4 | #import 5 | #import "MKTNonObjectArgumentMatching.h" 6 | 7 | @class MKTInvocationContainer; 8 | 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | /*! 13 | * @abstract Methods to invoke on given(methodCall) to stub return values or behaviors. 14 | * @discussion The methods return self to allow stubbing consecutive calls. The last 15 | * stub determines the behavior of further consecutive calls. 16 | */ 17 | @interface MKTOngoingStubbing : NSObject 18 | 19 | - (instancetype)initWithInvocationContainer:(MKTInvocationContainer *)invocationContainer NS_DESIGNATED_INITIALIZER; 20 | - (instancetype)init NS_UNAVAILABLE; 21 | 22 | /*! 23 | * @abstract Sets an object to return when the method is called. 24 | * @discussion Example: 25 | *
[given([mock someMethod]) willReturn:@"FOO"];
26 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 27 | */ 28 | - (MKTOngoingStubbing *)willReturn:(nullable id)object; 29 | 30 | /*! 31 | * @abstract Sets a struct to return when the method is called. 32 | * @param value Pointer to struct. 33 | * @param type \@encode() compiler directive called on the struct. 34 | * @discussion 35 | * Example: 36 | *
[given([mock someMethod]) willReturnStruct:&myStruct objCType:\@encode(MyStructType)];
37 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 38 | */ 39 | - (MKTOngoingStubbing *)willReturnStruct:(const void *)value objCType:(const char *)type; 40 | 41 | /*! 42 | * @abstract Sets a BOOL to return when the method is called. 43 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 44 | */ 45 | - (MKTOngoingStubbing *)willReturnBool:(BOOL)value; 46 | 47 | /*! 48 | * @abstract Sets a char to return when the method is called. 49 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 50 | */ 51 | - (MKTOngoingStubbing *)willReturnChar:(char)value; 52 | 53 | /*! 54 | * @abstract Sets an int to return when the method is called. 55 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 56 | */ 57 | - (MKTOngoingStubbing *)willReturnInt:(int)value; 58 | 59 | /*! 60 | * @abstract Sets a short to return when the method is called. 61 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 62 | */ 63 | - (MKTOngoingStubbing *)willReturnShort:(short)value; 64 | 65 | /*! 66 | * @abstract Sets a long to return when the method is called. 67 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 68 | */ 69 | - (MKTOngoingStubbing *)willReturnLong:(long)value; 70 | 71 | /*! 72 | * @abstract Sets a long long to return when the method is called. 73 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 74 | */ 75 | - (MKTOngoingStubbing *)willReturnLongLong:(long long)value; 76 | 77 | /*! 78 | * @abstract Sets an NSInteger to return when the method is called. 79 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 80 | */ 81 | - (MKTOngoingStubbing *)willReturnInteger:(NSInteger)value; 82 | 83 | /*! 84 | * @abstract Sets an unsigned char to return when the method is called. 85 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 86 | */ 87 | - (MKTOngoingStubbing *)willReturnUnsignedChar:(unsigned char)value; 88 | 89 | /*! 90 | * @abstract Sets an unsigned int to return when the method is called. 91 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 92 | */ 93 | - (MKTOngoingStubbing *)willReturnUnsignedInt:(unsigned int)value; 94 | 95 | /*! 96 | * @abstract Sets an unsigned short to return when the method is called. 97 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 98 | */ 99 | - (MKTOngoingStubbing *)willReturnUnsignedShort:(unsigned short)value; 100 | 101 | /*! 102 | * @abstract Sets an unsigned long to return when the method is called. 103 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 104 | */ 105 | - (MKTOngoingStubbing *)willReturnUnsignedLong:(unsigned long)value; 106 | 107 | /*! 108 | * @abstract Sets an unsigned long long to return when the method is called. 109 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 110 | */ 111 | - (MKTOngoingStubbing *)willReturnUnsignedLongLong:(unsigned long long)value; 112 | 113 | /*! 114 | * @abstract Sets an NSUInteger to return when the method is called. 115 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 116 | */ 117 | - (MKTOngoingStubbing *)willReturnUnsignedInteger:(NSUInteger)value; 118 | 119 | /*! 120 | * @abstract Sets a float to return when the method is called. 121 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 122 | */ 123 | - (MKTOngoingStubbing *)willReturnFloat:(float)value; 124 | 125 | /*! 126 | * @abstract Sets a double to return when the method is called. 127 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 128 | */ 129 | - (MKTOngoingStubbing *)willReturnDouble:(double)value; 130 | 131 | /*! 132 | * @abstract Sets an NSException to be thrown when the method is called. 133 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 134 | * @discussion 135 | * Example: 136 | *
[given([mock someMethod]) willThrow:exception];
137 | */ 138 | - (MKTOngoingStubbing *)willThrow:(NSException *)exception; 139 | 140 | /*! 141 | * @abstract Sets a block to be executed when the method is called. 142 | * @discussion The block is evaluated when the method is called. The block can easily access 143 | * invocation arguments by calling mkt_arguments. Whatever the block returns will be 144 | * used as the stubbed return value. 145 | * @return MKTOngoingStubbing object to allow stubbing consecutive calls 146 | */ 147 | - (MKTOngoingStubbing *)willDo:(id (^)(NSInvocation *))block; 148 | 149 | @end 150 | 151 | NS_ASSUME_NONNULL_END 152 | 153 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/MKTProtocolMock.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | 4 | #import "MKTBaseMockObject.h" 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract Mock object implementing a given protocol. 11 | */ 12 | @interface MKTProtocolMock : MKTBaseMockObject 13 | 14 | @property (nonatomic, strong, readonly) Protocol *mockedProtocol; 15 | 16 | - (instancetype)initWithProtocol:(Protocol *)aProtocol 17 | includeOptionalMethods:(BOOL)includeOptionalMethods NS_DESIGNATED_INITIALIZER; 18 | - (instancetype)init NS_UNAVAILABLE; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Headers/NSInvocation+OCMockito.h: -------------------------------------------------------------------------------- 1 | // OCMockito by Jon Reid, https://qualitycoding.org/ 2 | // Copyright 2018 Jonathan M. Reid. See LICENSE.txt 3 | 4 | #import 5 | 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | /*! 10 | * @abstract NSInvocation helper methods 11 | */ 12 | @interface NSInvocation (OCMockito) 13 | 14 | /*! 15 | * @abstract Returns all invocation arguments in an NSArray. 16 | * @discussion Non-object arguments are boxed as follows: 17 | *
    18 | *
  • nil: NSNull
  • 19 | *
  • Primitive numeric values: NSNumber
  • 20 | *
  • Pointers: NSValue
  • 21 | *
  • Selectors: NSString
  • 22 | *
  • Structs: NSData
  • 23 | *
24 | */ 25 | - (NSArray *)mkt_arguments; 26 | 27 | /*! @abstract Sets invocation return value. */ 28 | - (void)mkt_setReturnValue:(id)returnValue; 29 | 30 | /*! @abstract Retains arguments but with weak invocation target to avoid retain cycles. */ 31 | - (void)mkt_retainArgumentsWithWeakTarget; 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END 36 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module OCMockito { 2 | umbrella header "OCMockito.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/OCMockito: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewchidden/btt-services/eaf4f5bb711c900ec0bc1fe6c16f9dd40c75f877/Tests/Frameworks/OCMockito.framework/Versions/A/OCMockito -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 16G1212 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | OCMockito 11 | CFBundleIdentifier 12 | org.mockito.OCMockito 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | OCMockito 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 5.1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleSupportedPlatforms 24 | 25 | MacOSX 26 | 27 | CFBundleVersion 28 | 5.1.0 29 | DTCompiler 30 | com.apple.compilers.llvm.clang.1_0 31 | DTPlatformBuild 32 | 9C40b 33 | DTPlatformVersion 34 | GM 35 | DTSDKBuild 36 | 17C76 37 | DTSDKName 38 | macosx10.13 39 | DTXcode 40 | 0920 41 | DTXcodeBuild 42 | 9C40b 43 | NSHumanReadableCopyright 44 | Copyright © 2018 Jonathan M. Reid 45 | 46 | 47 | -------------------------------------------------------------------------------- /Tests/Frameworks/OCMockito.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Tests/NSDictionaryCTSCommandLineArgumentsTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import "NSDictionary+CTSCommandLineArguments.h" 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface NSDictionaryCTSCommandLineArgumentsTests : XCTestCase 10 | 11 | @end 12 | 13 | @implementation NSDictionaryCTSCommandLineArgumentsTests 14 | 15 | - (void)testCommandLineArgumentsParsedIntoDictionary 16 | { 17 | // Given an array of command-line arguments 18 | NSArray * const commandLineArgumentsMock = @[ 19 | @"/usr/local/bin/foo-bar-service", 20 | @"--foo=bar", 21 | @"-k", @"value", 22 | @"--one=plus two = three", 23 | @"not-an-argument", 24 | ]; 25 | 26 | // When the category parses the command-line arguments 27 | NSDictionary * const argumentsDictionary = 28 | [NSDictionary cts_dictionaryWithCommandLineArguments:commandLineArgumentsMock]; 29 | 30 | // Then the dictionary should have the expectedkey-value option pairs. 31 | assertThat(argumentsDictionary, equalTo(@{ 32 | @"foo" : @"bar", 33 | @"k" : @"value", 34 | @"one" : @"plus two = three", 35 | })); 36 | } 37 | 38 | - (void)testAlwaysIgnoresFirstArgument 39 | { 40 | assertThat([NSDictionary cts_dictionaryWithCommandLineArguments:@[@"--ignored=argument"]], equalTo(@{})); 41 | } 42 | 43 | @end 44 | 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /Tests/NSStringCTSReadableEventStatusTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import 6 | 7 | #import "NSString+CTSReadableEventStatus.h" 8 | 9 | NS_ASSUME_NONNULL_BEGIN 10 | 11 | @interface NSStringCTSReadableEventStatusTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation NSStringCTSReadableEventStatusTests 16 | 17 | - (void)testStringWithTimeInterval 18 | { 19 | assertThat([NSString cts_stringWithTimeInterval:60*1.0], equalTo(@"1 min")); 20 | assertThat([NSString cts_stringWithTimeInterval:60*2.33], equalTo(@"2 mins")); 21 | assertThat([NSString cts_stringWithTimeInterval:60*2.5], equalTo(@"3 mins")); 22 | assertThat([NSString cts_stringWithTimeInterval:(60*60*0.999)], equalTo(@"1 hr")); 23 | assertThat([NSString cts_stringWithTimeInterval:(60*60*1.0)], equalTo(@"1 hr")); 24 | assertThat([NSString cts_stringWithTimeInterval:(60*60*1.33)], equalTo(@"1.3 hrs")); 25 | assertThat([NSString cts_stringWithTimeInterval:(60*60*2.0)], equalTo(@"2 hrs")); 26 | 27 | assertThat([NSString cts_stringWithTimeInterval:(-60*1.0)], equalTo(@"-1 min")); 28 | assertThat([NSString cts_stringWithTimeInterval:(-60*2.33)], equalTo(@"-2 mins")); 29 | assertThat([NSString cts_stringWithTimeInterval:(-60*60*2.0)], equalTo(@"-2 hrs")); 30 | } 31 | 32 | - (void)testEventStatusString 33 | { 34 | // Given an event that has not yet started 35 | EKEvent * const eventMock = mock([EKEvent class]); 36 | [given(eventMock.title) willReturn:@"Top Secret Meeting"]; 37 | [given(eventMock.startDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:60*60*1.33]]; 38 | [given(eventMock.endDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:60*60*2.33]]; 39 | // When the category turns the event into a readable string Then the status should be as expected. 40 | assertThat([NSString cts_stringStatusWithEvent:eventMock referenceDate:[NSDate date]], 41 | equalTo(@"Top Secret Meeting in 1.3 hrs")); 42 | 43 | // Given an event that has already started 44 | EKEvent * const startedEventMock = mock([EKEvent class]); 45 | [given(startedEventMock.title) willReturn:@"Top Secret Meeting"]; 46 | [given(startedEventMock.startDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:-60*60*1.33]]; 47 | [given(startedEventMock.endDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:60*60*1.0]]; 48 | // When the category turns the event into a readable string Then the status should be as expected. 49 | assertThat([NSString cts_stringStatusWithEvent:startedEventMock referenceDate:[NSDate date]], 50 | equalTo(@"Top Secret Meeting ending in 1 hr")); 51 | } 52 | 53 | - (void)testEventStatusTrimsWhitespace 54 | { 55 | // Given an event that has leading and trailing whitespace in the title 56 | EKEvent * const eventMock = mock([EKEvent class]); 57 | [given(eventMock.title) willReturn:@" Top Secret Meeting "]; 58 | [given(eventMock.startDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:60*60*1.33]]; 59 | [given(eventMock.endDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:60*60*2.33]]; 60 | // When the category turns the event into a readable string Then the event title's whitespace should be trimmed. 61 | assertThat([NSString cts_stringStatusWithEvent:eventMock referenceDate:[NSDate date]], 62 | equalTo(@"Top Secret Meeting in 1.3 hrs")); 63 | } 64 | 65 | - (void)testEventStatusHandlesEndedEvents 66 | { 67 | // Given an event that has ended 68 | EKEvent * const eventMock = mock([EKEvent class]); 69 | [given(eventMock.title) willReturn:@"Top Secret Meeting"]; 70 | [given(eventMock.startDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:-60*60*2.0]]; 71 | [given(eventMock.endDate) willReturn:[NSDate dateWithTimeIntervalSinceNow:-60*60*1.0]]; 72 | // When the category turns the event into a readable string Then the event time should be capped at 0 min. 73 | assertThat([NSString cts_stringStatusWithEvent:eventMock referenceDate:[NSDate date]], 74 | equalTo(@"Top Secret Meeting ending in 0 mins")); 75 | } 76 | 77 | @end 78 | 79 | NS_ASSUME_NONNULL_END 80 | -------------------------------------------------------------------------------- /Tests/NSStringCTSSerializedVolumeStatusTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import "NSString+CTSSerializedVolumeStatus.h" 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface NSStringCTSSerializedVolumeStatusTests : XCTestCase 10 | 11 | @end 12 | 13 | @implementation NSStringCTSSerializedVolumeStatusTests 14 | 15 | - (void)testStringWithTimeInterval 16 | { 17 | assertThat([NSString cts_stringStatusWithVolume:0 muteState:NO], equalTo(@"0")); 18 | assertThat([NSString cts_stringStatusWithVolume:30 muteState:NO], equalTo(@"30")); 19 | assertThat([NSString cts_stringStatusWithVolume:0 muteState:YES], equalTo(@"-0")); 20 | assertThat([NSString cts_stringStatusWithVolume:30 muteState:YES], equalTo(@"-30")); 21 | } 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /Tests/NSURLCTSBetterTouchToolWebServerEndpointTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import "CTSBetterTouchToolWebServerConfiguration.h" 6 | #import "NSURL+CTSBetterTouchToolWebServerEndpoint.h" 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | @interface NSURLCTSBetterTouchToolWebServerEndpointTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation NSURLCTSBetterTouchToolWebServerEndpointTests 15 | 16 | - (void)testURLConstructionWithConfiguration 17 | { 18 | // Given a web server configuration 19 | CTSBetterTouchToolWebServerConfiguration * const configurationMock = 20 | mock([CTSBetterTouchToolWebServerConfiguration class]); 21 | [given(configurationMock.URL) willReturn:[NSURL URLWithString:@"http://127.0.0.1:12345/"]]; 22 | [given(configurationMock.sharedSecret) willReturn:@"a-very-secret-key"]; 23 | 24 | // When constructing a new URL to the `refresh_widget` endpoint 25 | NSURL * const URL = [NSURL cts_URLWithWebServerConfiguration:configurationMock 26 | endpoint:@"refresh_widget" 27 | queryParameters:@[@"uuid=foo-bar"]]; 28 | 29 | // Then the category should use the configuration and parameters to decorate the URL. 30 | NSURL * const expectedURL = 31 | [NSURL URLWithString:@"http://127.0.0.1:12345/refresh_widget/?uuid=foo-bar&shared_secret=a-very-secret-key"]; 32 | assertThat(URL, equalTo(expectedURL)); 33 | } 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /Tests/Stubs/CTSAudioToolboxControlStripServiceTestStub.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | /** 5 | Stubbed AudioToolbox definitions for testing @c CTSControlStripService. 6 | */ 7 | extern OSStatus AudioServicesCreateSystemSoundID(CFURLRef inFileURL, 8 | SystemSoundID *outSystemSoundID) __attribute__((weak)); 9 | 10 | extern void AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID) __attribute__((weak)); 11 | 12 | /** 13 | A @c CTSAudioServicesMock object provides Objective-C method bindings between the test runner and OCMockito. 14 | */ 15 | @interface CTSAudioServicesMock : NSObject 16 | 17 | - (OSStatus)audioServicesCreateSystemSoundID:(CFURLRef)inFileURL 18 | outSystemSoundID:(SystemSoundID *)outSystemSoundID; 19 | 20 | - (void)audioServicesPlaySystemSound:(SystemSoundID)inSystemSoundID; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Tests/Stubs/CTSAudioToolboxControlStripServiceTestStub.m: -------------------------------------------------------------------------------- 1 | #import "CTSAudioToolboxControlStripServiceTestStub.h" 2 | 3 | OSStatus AudioServicesCreateSystemSoundID(CFURLRef inFileURL, 4 | SystemSoundID *outSystemSoundID) 5 | { 6 | return noErr; 7 | } 8 | 9 | void AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID) 10 | { 11 | } 12 | 13 | @implementation CTSAudioServicesMock 14 | 15 | - (OSStatus)audioServicesCreateSystemSoundID:(CFURLRef)inFileURL 16 | outSystemSoundID:(SystemSoundID *)outSystemSoundID 17 | { 18 | return noErr; 19 | } 20 | 21 | - (void)audioServicesPlaySystemSound:(SystemSoundID)inSystemSoundID 22 | { 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Tests/Stubs/CTSAudioToolboxVolumeServiceTestStub.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | /** 6 | Stubbed AudioToolbox definitions for testing @c CTSVolumeService. 7 | */ 8 | 9 | CF_ENUM(AudioObjectPropertySelector) 10 | { 11 | kAudioHardwareServiceProperty_ServiceRestarted = 'srst', 12 | kAudioHardwareServiceDeviceProperty_VirtualMasterVolume = 'vmvc', 13 | kAudioHardwareServiceDeviceProperty_VirtualMasterBalance = 'vmbc', 14 | }; 15 | 16 | extern OSStatus AudioObjectAddPropertyListener(AudioObjectID inObjectID, 17 | const AudioObjectPropertyAddress *inAddress, 18 | AudioObjectPropertyListenerProc inListener, 19 | void * __nullable inClientData) __attribute__((weak)); 20 | 21 | extern OSStatus AudioHardwareServiceAddPropertyListener(AudioObjectID inObjectID, 22 | const AudioObjectPropertyAddress *inAddress, 23 | AudioObjectPropertyListenerProc inListener, 24 | void *inClientData) __attribute__((weak)); 25 | 26 | extern OSStatus AudioHardwareServiceRemovePropertyListener(AudioObjectID inObjectID, 27 | const AudioObjectPropertyAddress *inAddress, 28 | AudioObjectPropertyListenerProc inListener, 29 | void *inClientData) __attribute__((weak)); 30 | 31 | extern OSStatus AudioHardwareServiceGetPropertyData(AudioObjectID inObjectID, 32 | const AudioObjectPropertyAddress *inAddress, 33 | UInt32 inQualifierDataSize, 34 | const void *inQualifierData, 35 | UInt32 *ioDataSize, 36 | void *outData) __attribute__((weak)); 37 | 38 | /** 39 | A @c CTSAudioHardwareServiceMock object provides Objective-C method bindings between the test runner and OCMockito. 40 | */ 41 | @interface CTSAudioHardwareServiceMock : NSObject 42 | 43 | - (OSStatus)audioObjectAddPropertyListener:(AudioObjectID)inObjectID 44 | inAddress:(const AudioObjectPropertyAddress *)inAddress 45 | inListener:(AudioObjectPropertyListenerProc)inListener 46 | inClientData:(void *)inClientData; 47 | 48 | - (OSStatus)audioHardwareServiceAddPropertyListener:(AudioObjectID)inObjectID 49 | inAddress:(const AudioObjectPropertyAddress *)inAddress 50 | inListener:(AudioObjectPropertyListenerProc)inListener 51 | inClientData:(void *)inClientData; 52 | 53 | - (OSStatus)audioHardwareServiceRemovePropertyListener:(AudioObjectID)inObjectID 54 | inAddress:(const AudioObjectPropertyAddress *)inAddress 55 | inListener:(AudioObjectPropertyListenerProc)inListener 56 | inClientData:(void *)inClientData; 57 | 58 | - (OSStatus)audioHardwareServiceGetPropertyData:(AudioObjectID)inObjectID 59 | inAddress:(const AudioObjectPropertyAddress *)inAddress 60 | inQualifierDataSize:(UInt32)inQualifierDataSize 61 | inQualifierData:(const void *)inQualifierData 62 | ioDataSize:(UInt32 *)ioDataSize 63 | outData:(void *)outData; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Tests/Stubs/CTSAudioToolboxVolumeServiceTestStub.m: -------------------------------------------------------------------------------- 1 | #import "CTSAudioToolboxVolumeServiceTestStub.h" 2 | 3 | OSStatus AudioObjectAddPropertyListener(AudioObjectID inObjectID, 4 | const AudioObjectPropertyAddress *inAddress, 5 | AudioObjectPropertyListenerProc inListener, 6 | void * __nullable inClientData) 7 | { 8 | return noErr; 9 | } 10 | 11 | OSStatus AudioHardwareServiceAddPropertyListener(AudioObjectID inObjectID, 12 | const AudioObjectPropertyAddress *inAddress, 13 | AudioObjectPropertyListenerProc inListener, 14 | void *inClientData) 15 | { 16 | return noErr; 17 | } 18 | 19 | OSStatus AudioHardwareServiceRemovePropertyListener(AudioObjectID inObjectID, 20 | const AudioObjectPropertyAddress *inAddress, 21 | AudioObjectPropertyListenerProc inListener, 22 | void *inClientData) 23 | { 24 | return noErr; 25 | } 26 | 27 | OSStatus AudioHardwareServiceGetPropertyData(AudioObjectID inObjectID, 28 | const AudioObjectPropertyAddress *inAddress, 29 | UInt32 inQualifierDataSize, 30 | const void *inQualifierData, 31 | UInt32 *ioDataSize, 32 | void *outData) 33 | { 34 | return noErr; 35 | } 36 | 37 | 38 | @implementation CTSAudioHardwareServiceMock 39 | 40 | - (OSStatus)audioObjectAddPropertyListener:(AudioObjectID)inObjectID 41 | inAddress:(const AudioObjectPropertyAddress *)inAddress 42 | inListener:(AudioObjectPropertyListenerProc)inListener 43 | inClientData:(void *)inClientData 44 | { 45 | return noErr; 46 | } 47 | 48 | - (OSStatus)audioHardwareServiceAddPropertyListener:(AudioObjectID)inObjectID 49 | inAddress:(const AudioObjectPropertyAddress *)inAddress 50 | inListener:(AudioObjectPropertyListenerProc)inListener 51 | inClientData:(void *)inClientData 52 | { 53 | return noErr; 54 | } 55 | 56 | - (OSStatus)audioHardwareServiceRemovePropertyListener:(AudioObjectID)inObjectID 57 | inAddress:(const AudioObjectPropertyAddress *)inAddress 58 | inListener:(AudioObjectPropertyListenerProc)inListener 59 | inClientData:(void *)inClientData 60 | { 61 | return noErr; 62 | } 63 | 64 | - (OSStatus)audioHardwareServiceGetPropertyData:(AudioObjectID)inObjectID 65 | inAddress:(const AudioObjectPropertyAddress *)inAddress 66 | inQualifierDataSize:(UInt32)inQualifierDataSize 67 | inQualifierData:(const void *)inQualifierData 68 | ioDataSize:(UInt32 *)ioDataSize 69 | outData:(void *)outData 70 | { 71 | return noErr; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Tests/Stubs/CTSCoreGraphicsEventControlStripServiceTestStub.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | CG_EXTERN void CGEventPost(CGEventTapLocation tap, CGEventRef __nullable event) __attribute__((weak)); 5 | 6 | /** 7 | A @c CTSCoreGraphicsEventMock object provides Objective-C method bindings between the test runner and OCMockito. 8 | */ 9 | @interface CTSCoreGraphicsEventMock : NSObject 10 | 11 | - (void)cgEventPost:(CGEventTapLocation)tap event:(CGEventRef __nullable)event; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Tests/Stubs/CTSCoreGraphicsEventControlStripServiceTestStub.m: -------------------------------------------------------------------------------- 1 | #import "CTSCoreGraphicsEventControlStripServiceTestStub.h" 2 | 3 | void CGEventPost(CGEventTapLocation tap, CGEventRef __nullable event) 4 | { 5 | } 6 | 7 | @implementation CTSCoreGraphicsEventMock 8 | 9 | - (void)cgEventPost:(CGEventTapLocation)tap event:(CGEventRef __nullable)event 10 | { 11 | } 12 | 13 | @end 14 | --------------------------------------------------------------------------------