From a5401bc05c5eacaa49ab0ce888b08edbaf051e8e Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 13:51:33 -0400 Subject: [PATCH 1/8] Add nullability annotation for functions that may return nil if there is an issue reading the input file. --- .../Sources/Mocktail/OHHTTPStubs+Mocktail.h | 4 +-- .../Sources/Mocktail/OHHTTPStubs+Mocktail.m | 4 +-- .../UnitTests/Test Suites/MocktailTests.m | 33 +++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h index c7ef6afa..345ccf65 100644 --- a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h +++ b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h @@ -65,7 +65,7 @@ extern NSString* const MocktailErrorDomain; * @return a stub descriptor that uniquely identifies the stub and can be later used to remove it with * `removeStub:`. */ -+(id)stubRequestsUsingMocktailNamed:(NSString *)fileName inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error; ++(nullable id)stubRequestsUsingMocktailNamed:(NSString *)fileName inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error; /** * Add a stub given a file URL in the format of Mocktail as defined at https://github.com/square/objc-mocktail. @@ -93,7 +93,7 @@ extern NSString* const MocktailErrorDomain; * @return an array of stub descriptor that uniquely identifies the stub and can be later used to remove it with * `removeStub:`. */ -+(NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error; ++(nullable NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error; @end diff --git a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m index 9575947b..cd3f767b 100644 --- a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m +++ b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m @@ -32,7 +32,7 @@ @implementation OHHTTPStubs (Mocktail) -+(NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error ++(nullable NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error { NSURL *dirURL = [bundleOrNil?:[NSBundle bundleForClass:self.class] URLForResource:path withExtension:nil]; if (!dirURL) @@ -90,7 +90,7 @@ +(NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable return descriptorArray; } -+(id)stubRequestsUsingMocktailNamed:(NSString *)fileName inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error ++(nullable id)stubRequestsUsingMocktailNamed:(NSString *)fileName inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error { NSURL *responseURL = [bundleOrNil?:[NSBundle bundleForClass:self.class] URLForResource:fileName withExtension:@"tail"]; diff --git a/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m b/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m index 73e09317..28c9bd37 100644 --- a/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m +++ b/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m @@ -66,6 +66,17 @@ - (void)testMocktailLoginSuccess [self runLogin]; } +- (void)testMocktailFailsWithInvalidInputFile +{ + NSError *error = nil; + NSBundle *bundle = [NSBundle bundleForClass:self.class]; + id descriptor = [OHHTTPStubs stubRequestsUsingMocktailNamed:@"invalid file name" inBundle:bundle error:&error]; + XCTAssertNil(descriptor, @"Invalid input failed to produce nil result"); + XCTAssertEqualObjects(error.domain, MocktailErrorDomain); + XCTAssertEqual(error.code, OHHTTPStubsMocktailErrorPathDoesNotExist); + XCTAssertEqualObjects(error.userInfo[NSLocalizedDescriptionKey], @"File 'invalid file name' does not exist."); +} + - (void)testMocktailsAtFolder { NSError *error = nil; @@ -76,6 +87,28 @@ - (void)testMocktailsAtFolder [self runGetCards]; } +- (void)testMocktailsFailWithNonexistentFolder +{ + NSError *error = nil; + NSBundle *bundle = [NSBundle bundleForClass:self.class]; + NSArray *descriptors = [OHHTTPStubs stubRequestsUsingMocktailsAtPath:@"invalid folder name" inBundle:bundle error:&error]; + XCTAssertNil(descriptors, @"Invalid input failed to produce nil result"); + XCTAssertEqualObjects(error.domain, MocktailErrorDomain); + XCTAssertEqual(error.code, OHHTTPStubsMocktailErrorPathDoesNotExist); + XCTAssertEqualObjects(error.userInfo[NSLocalizedDescriptionKey], @"Path 'invalid folder name' does not exist."); +} + +- (void)testMocktailsFailWithNonFolderFile +{ + NSError *error = nil; + NSBundle *bundle = [NSBundle bundleForClass:self.class]; + NSArray *descriptors = [OHHTTPStubs stubRequestsUsingMocktailsAtPath:@"login.tail" inBundle:bundle error:&error]; + XCTAssertNil(descriptors, @"Invalid input failed to produce nil result"); + XCTAssertEqualObjects(error.domain, MocktailErrorDomain); + XCTAssertEqual(error.code, OHHTTPStubsMocktailErrorPathIsNotFolder); + XCTAssertEqualObjects(error.userInfo[NSLocalizedDescriptionKey], @"Path 'login.tail' is not a folder."); +} + - (void)testMocktailHeaders { NSError *error = nil; From 01826c30fe24f6870d408b46fbf543ee05f71d0d Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 14:15:37 -0400 Subject: [PATCH 2/8] Use Obj-C generics. --- OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h | 2 +- OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h index 345ccf65..f4dc1a60 100644 --- a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h +++ b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.h @@ -93,7 +93,7 @@ extern NSString* const MocktailErrorDomain; * @return an array of stub descriptor that uniquely identifies the stub and can be later used to remove it with * `removeStub:`. */ -+(nullable NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error; ++(nullable NSArray> *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error; @end diff --git a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m index cd3f767b..cbe1d8dd 100644 --- a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m +++ b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m @@ -32,7 +32,7 @@ @implementation OHHTTPStubs (Mocktail) -+(nullable NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error ++(nullable NSArray> *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle:(nullable NSBundle*)bundleOrNil error:(NSError **)error { NSURL *dirURL = [bundleOrNil?:[NSBundle bundleForClass:self.class] URLForResource:path withExtension:nil]; if (!dirURL) @@ -73,7 +73,7 @@ +(nullable NSArray *)stubRequestsUsingMocktailsAtPath:(NSString *)path inBundle: } //stub the Mocktail-formatted requests - NSMutableArray *descriptorArray = [[NSMutableArray alloc] initWithCapacity:fileURLs.count]; + NSMutableArray> *descriptorArray = [[NSMutableArray alloc] initWithCapacity:fileURLs.count]; for (NSURL *fileURL in fileURLs) { if (![fileURL.absoluteString hasSuffix:@".tail"]) From 91224e033cfd98efc43db2c2e94086666bf71ca7 Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 14:16:17 -0400 Subject: [PATCH 3/8] Use more accurate property annotation to silence static analysis warning. --- OHHTTPStubs/Sources/OHHTTPStubs.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OHHTTPStubs/Sources/OHHTTPStubs.m b/OHHTTPStubs/Sources/OHHTTPStubs.m index 3a0eaf8f..12be2eb7 100644 --- a/OHHTTPStubs/Sources/OHHTTPStubs.m +++ b/OHHTTPStubs/Sources/OHHTTPStubs.m @@ -43,7 +43,7 @@ @interface OHHTTPStubsProtocol : NSURLProtocol @end @interface OHHTTPStubs() + (instancetype)sharedInstance; -@property(atomic, copy) NSMutableArray* stubDescriptors; +@property(atomic, readonly) NSMutableArray* stubDescriptors; @property(atomic, assign) BOOL enabledState; @property(atomic, copy, nullable) void (^onStubActivationBlock)(NSURLRequest*, id, OHHTTPStubsResponse*); @property(atomic, copy, nullable) void (^onStubRedirectBlock)(NSURLRequest*, NSURLRequest*, id, OHHTTPStubsResponse*); From d3985e153f3751383bbd85b556b869b37a2a8ea3 Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 14:29:17 -0400 Subject: [PATCH 4/8] More idiomatic Objective-C error handling: treat error parameter as undefined unless result signals failure via a nil value. --- .../Sources/Mocktail/OHHTTPStubs+Mocktail.m | 27 +++++++++---------- .../UnitTests/Test Suites/MocktailTests.m | 7 ++--- .../UnitTests/Test Suites/NSURLSessionTests.m | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m index cbe1d8dd..83932dd9 100644 --- a/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m +++ b/OHHTTPStubs/Sources/Mocktail/OHHTTPStubs+Mocktail.m @@ -59,11 +59,10 @@ @implementation OHHTTPStubs (Mocktail) } // Read the content of the directory - NSError *bError = nil; NSFileManager *fileManager = [NSFileManager defaultManager]; - NSArray *fileURLs = [fileManager contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:nil options:0 error:&bError]; + NSArray *fileURLs = [fileManager contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:nil options:0 error:nil]; - if (bError) + if (!fileURLs) { if (error) { @@ -80,8 +79,8 @@ @implementation OHHTTPStubs (Mocktail) { continue; } - id descriptor = [[self class] stubRequestsUsingMocktail:fileURL error: &bError]; - if (descriptor && !bError) + id descriptor = [[self class] stubRequestsUsingMocktail:fileURL error: nil]; + if (descriptor) { [descriptorArray addObject:descriptor]; } @@ -114,7 +113,7 @@ @implementation OHHTTPStubs (Mocktail) NSStringEncoding originalEncoding; NSString *contentsOfFile = [NSString stringWithContentsOfURL:fileURL usedEncoding:&originalEncoding error:&bError]; - if (!contentsOfFile || bError) + if (!contentsOfFile) { if (error) { @@ -138,9 +137,9 @@ @implementation OHHTTPStubs (Mocktail) /* Handle Mocktail format, adapted from Mocktail implementation For more details on the file format, check out: https://github.com/square/objc-Mocktail */ - NSRegularExpression *methodRegex = [NSRegularExpression regularExpressionWithPattern:lines[0] options:NSRegularExpressionCaseInsensitive error:&bError]; + NSRegularExpression *methodRegex = [NSRegularExpression regularExpressionWithPattern:lines[0] options:NSRegularExpressionCaseInsensitive error:nil]; - if (bError) + if (!methodRegex) { if (error) { @@ -149,9 +148,9 @@ @implementation OHHTTPStubs (Mocktail) return nil; } - NSRegularExpression *absoluteURLRegex = [NSRegularExpression regularExpressionWithPattern:lines[1] options:NSRegularExpressionCaseInsensitive error:&bError]; + NSRegularExpression *absoluteURLRegex = [NSRegularExpression regularExpressionWithPattern:lines[1] options:NSRegularExpressionCaseInsensitive error:nil]; - if (bError) + if (!absoluteURLRegex) { if (error) { @@ -165,8 +164,8 @@ @implementation OHHTTPStubs (Mocktail) NSMutableDictionary *headers = @{@"Content-Type":lines[3]}.mutableCopy; // From line 4 to '\n\n', expect HTTP response headers. - NSRegularExpression *headerPattern = [NSRegularExpression regularExpressionWithPattern:@"^([^:]+):\\s+(.*)" options:0 error:&bError]; - if (bError) + NSRegularExpression *headerPattern = [NSRegularExpression regularExpressionWithPattern:@"^([^:]+):\\s+(.*)" options:0 error:nil]; + if (!headerPattern) { if (error) { @@ -177,8 +176,8 @@ @implementation OHHTTPStubs (Mocktail) // Allow bare Content-Type header on line 4 before named HTTP response headers - NSRegularExpression *bareContentTypePattern = [NSRegularExpression regularExpressionWithPattern:@"^([^:]+)+$" options:0 error:&bError]; - if (bError) + NSRegularExpression *bareContentTypePattern = [NSRegularExpression regularExpressionWithPattern:@"^([^:]+)+$" options:0 error:nil]; + if (!bareContentTypePattern) { if (error) { diff --git a/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m b/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m index 28c9bd37..cd5073c7 100644 --- a/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m +++ b/OHHTTPStubs/UnitTests/Test Suites/MocktailTests.m @@ -200,12 +200,13 @@ - (NSHTTPURLResponse *)runGetCards XCTAssertNil(error, @"Error while getting cards."); NSArray *json = nil; - if(!error && [@"application/json" isEqual:response.MIMEType]) + NSError *jsonError = nil; + if([@"application/json" isEqualToString:response.MIMEType]) { - json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError]; } - XCTAssertNotNil(json, @"The response is not a json object"); + XCTAssertNotNil(json, @"The response is not a json object: %@", jsonError); XCTAssertEqual(json.count, 2, @"The response does not contain 2 cards"); XCTAssertEqualObjects([json firstObject][@"amount"], @"$25.28", @"The first card amount does not match"); diff --git a/OHHTTPStubs/UnitTests/Test Suites/NSURLSessionTests.m b/OHHTTPStubs/UnitTests/Test Suites/NSURLSessionTests.m index e5e0a6a3..ca04b0ba 100644 --- a/OHHTTPStubs/UnitTests/Test Suites/NSURLSessionTests.m +++ b/OHHTTPStubs/UnitTests/Test Suites/NSURLSessionTests.m @@ -89,7 +89,7 @@ - (void)_test_NSURLSession:(NSURLSession*)session { NSError *jsonError = nil; NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError]; - XCTAssertNil(jsonError, @"Unexpected error deserializing JSON response"); + XCTAssertNotNil(jsonObject, @"Unexpected error deserializing JSON response: %@", jsonError); dataResponse = jsonObject; } [expectation fulfill]; From fb7f06244982bb8f9864aee2bc01d9f61fe0244d Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 14:31:06 -0400 Subject: [PATCH 5/8] Fix copypasta. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 868d5ff4..d1e3d6cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # OHHTTPStubs — CHANGELOG -## [8.0.0](https://github.com/AliSoftware/OHHTTPStubs/releases/tag/7.0.0) +## [8.0.0](https://github.com/AliSoftware/OHHTTPStubs/releases/tag/8.0.0) * Update default Swift Version to 5.0 [@croig](https://github.com/CRoig) From ccc693a666294876f54d814bc86718de75aa4700 Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 14:31:16 -0400 Subject: [PATCH 6/8] Fix typo. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1e3d6cc..62dbf9ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ [@croig](https://github.com/CRoig) >Notes: -> * No code changes were required (except from a little missing comma which caused a compilation error). Only xcshemes and xcodeproj were changed. +> * No code changes were required (except from a little missing comma which caused a compilation error). Only xcschemes and xcodeproj were changed. ## [7.0.0](https://github.com/AliSoftware/OHHTTPStubs/releases/tag/7.0.0) From efef60e706c049f9212d0b0efe908ade890cc49b Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 14:37:23 -0400 Subject: [PATCH 7/8] Add instructions to the release notes document. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62dbf9ec..7fe416af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # OHHTTPStubs — CHANGELOG + + ## [8.0.0](https://github.com/AliSoftware/OHHTTPStubs/releases/tag/8.0.0) * Update default Swift Version to 5.0 From 31ea4fbcd5e2c047ebb99ea952279b44e6755747 Mon Sep 17 00:00:00 2001 From: Zev Eisenberg Date: Wed, 18 Sep 2019 14:39:48 -0400 Subject: [PATCH 8/8] Update changelog. --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fe416af..d8d7d5e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ +* Fix clang static analysis warnings and use more idiomatic Objective-C error handling. + [@zeveisenberg](https://github.com/zeveisenberg) + ## [8.0.0](https://github.com/AliSoftware/OHHTTPStubs/releases/tag/8.0.0) * Update default Swift Version to 5.0