Isolated all testing code with __GCDWEBSERVER_ENABLE_TESTING__
This commit is contained in:
@ -65,12 +65,8 @@ typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* r
|
|||||||
@property(nonatomic, readonly) NSURL* serverURL; // Only non-nil if server is running
|
@property(nonatomic, readonly) NSURL* serverURL; // Only non-nil if server is running
|
||||||
@property(nonatomic, readonly) NSURL* bonjourServerURL; // Only non-nil if server is running and Bonjour registration is active
|
@property(nonatomic, readonly) NSURL* bonjourServerURL; // Only non-nil if server is running and Bonjour registration is active
|
||||||
#if !TARGET_OS_IPHONE
|
#if !TARGET_OS_IPHONE
|
||||||
@property(nonatomic, getter=isRecordingEnabled) BOOL recordingEnabled; // Creates files in the current directory containing the raw data for all requests and responses (directory most NOT contain prior recordings)
|
|
||||||
- (BOOL)runWithPort:(NSUInteger)port; // Starts then automatically stops on SIGINT i.e. Ctrl-C (use on main thread only)
|
- (BOOL)runWithPort:(NSUInteger)port; // Starts then automatically stops on SIGINT i.e. Ctrl-C (use on main thread only)
|
||||||
#endif
|
#endif
|
||||||
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
|
||||||
- (NSInteger)runTestsInDirectory:(NSString*)path withPort:(NSUInteger)port; // Returns number of failed tests or -1 if server failed to start
|
|
||||||
#endif
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface GCDWebServer (Handlers)
|
@interface GCDWebServer (Handlers)
|
||||||
@ -94,3 +90,12 @@ typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* r
|
|||||||
- (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
- (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
||||||
- (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
- (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
|
|
||||||
|
@interface GCDWebServer (Testing)
|
||||||
|
@property(nonatomic, getter=isRecordingEnabled) BOOL recordingEnabled; // Creates files in the current directory containing the raw data for all requests and responses (directory most NOT contain prior recordings)
|
||||||
|
- (NSInteger)runTestsInDirectory:(NSString*)path withPort:(NSUInteger)port; // Returns number of failed tests or -1 if server failed to start
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@ -49,7 +49,7 @@
|
|||||||
NSUInteger _port;
|
NSUInteger _port;
|
||||||
dispatch_source_t _source;
|
dispatch_source_t _source;
|
||||||
CFNetServiceRef _service;
|
CFNetServiceRef _service;
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
BOOL _recording;
|
BOOL _recording;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -334,18 +334,6 @@ static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* er
|
|||||||
|
|
||||||
@implementation GCDWebServer (Extensions)
|
@implementation GCDWebServer (Extensions)
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE
|
|
||||||
|
|
||||||
- (void)setRecordingEnabled:(BOOL)flag {
|
|
||||||
_recording = flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)isRecordingEnabled {
|
|
||||||
return _recording;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- (NSURL*)serverURL {
|
- (NSURL*)serverURL {
|
||||||
if (_source) {
|
if (_source) {
|
||||||
NSString* ipAddress = GCDWebServerGetPrimaryIPv4Address();
|
NSString* ipAddress = GCDWebServerGetPrimaryIPv4Address();
|
||||||
@ -395,177 +383,6 @@ static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* er
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
|
||||||
|
|
||||||
static CFHTTPMessageRef _CreateHTTPMessageFromData(NSData* data, BOOL isRequest) {
|
|
||||||
CFHTTPMessageRef message = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, isRequest);
|
|
||||||
if (CFHTTPMessageAppendBytes(message, data.bytes, data.length)) {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
CFRelease(message);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CFHTTPMessageRef _CreateHTTPMessageFromPerformingRequest(NSData* inData, NSUInteger port) {
|
|
||||||
CFHTTPMessageRef response = NULL;
|
|
||||||
int httpSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
if (httpSocket > 0) {
|
|
||||||
struct sockaddr_in addr4;
|
|
||||||
bzero(&addr4, sizeof(addr4));
|
|
||||||
addr4.sin_len = sizeof(port);
|
|
||||||
addr4.sin_family = AF_INET;
|
|
||||||
addr4.sin_port = htons(8080);
|
|
||||||
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
if (connect(httpSocket, (void*)&addr4, sizeof(addr4)) == 0) {
|
|
||||||
if (write(httpSocket, inData.bytes, inData.length) == (ssize_t)inData.length) {
|
|
||||||
NSMutableData* outData = [[NSMutableData alloc] initWithLength:(256 * 1024)];
|
|
||||||
NSUInteger length = 0;
|
|
||||||
while (1) {
|
|
||||||
ssize_t result = read(httpSocket, (char*)outData.mutableBytes + length, outData.length - length);
|
|
||||||
if (result < 0) {
|
|
||||||
length = NSNotFound;
|
|
||||||
break;
|
|
||||||
} else if (result == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
length += result;
|
|
||||||
if (length >= outData.length) {
|
|
||||||
outData.length = 2 * outData.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (length != NSNotFound) {
|
|
||||||
outData.length = length;
|
|
||||||
response = _CreateHTTPMessageFromData(outData, NO);
|
|
||||||
} else {
|
|
||||||
DNOT_REACHED();
|
|
||||||
}
|
|
||||||
ARC_RELEASE(outData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(httpSocket);
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _LogResult(NSString* format, ...) {
|
|
||||||
va_list arguments;
|
|
||||||
va_start(arguments, format);
|
|
||||||
NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments];
|
|
||||||
va_end(arguments);
|
|
||||||
fprintf(stdout, "%s\n", [message UTF8String]);
|
|
||||||
ARC_RELEASE(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSInteger)runTestsInDirectory:(NSString*)path withPort:(NSUInteger)port {
|
|
||||||
NSArray* ignoredHeaders = @[@"Date", @"Etag"]; // Dates are always different by definition and ETags depend on file system node IDs
|
|
||||||
NSInteger result = -1;
|
|
||||||
if ([self startWithPort:port bonjourName:nil]) {
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
|
|
||||||
for (NSString* requestFile in files) {
|
|
||||||
if (![requestFile hasSuffix:@".request"]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
@autoreleasepool {
|
|
||||||
NSString* index = [[requestFile componentsSeparatedByString:@"-"] firstObject];
|
|
||||||
BOOL success = NO;
|
|
||||||
NSData* requestData = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:requestFile]];
|
|
||||||
if (requestData) {
|
|
||||||
CFHTTPMessageRef request = _CreateHTTPMessageFromData(requestData, YES);
|
|
||||||
if (request) {
|
|
||||||
NSString* requestMethod = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestMethod(request));
|
|
||||||
NSURL* requestURL = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestURL(request));
|
|
||||||
_LogResult(@"[%i] %@ %@", (int)[index integerValue], requestMethod, requestURL.path);
|
|
||||||
NSString* prefix = [index stringByAppendingString:@"-"];
|
|
||||||
for (NSString* responseFile in files) {
|
|
||||||
if ([responseFile hasPrefix:prefix] && [responseFile hasSuffix:@".response"]) {
|
|
||||||
NSData* responseData = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:responseFile]];
|
|
||||||
if (responseData) {
|
|
||||||
CFHTTPMessageRef expectedResponse = _CreateHTTPMessageFromData(responseData, NO);
|
|
||||||
if (expectedResponse) {
|
|
||||||
CFHTTPMessageRef actualResponse = _CreateHTTPMessageFromPerformingRequest(requestData, port);
|
|
||||||
if (actualResponse) {
|
|
||||||
success = YES;
|
|
||||||
|
|
||||||
CFIndex expectedStatusCode = CFHTTPMessageGetResponseStatusCode(expectedResponse);
|
|
||||||
CFIndex actualStatusCode = CFHTTPMessageGetResponseStatusCode(actualResponse);
|
|
||||||
if (actualStatusCode != expectedStatusCode) {
|
|
||||||
_LogResult(@" Status code not matching:\n Expected: %i\n Actual: %i", (int)expectedStatusCode, (int)actualStatusCode);
|
|
||||||
success = NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSDictionary* expectedHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(expectedResponse));
|
|
||||||
NSDictionary* actualHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(actualResponse));
|
|
||||||
for (NSString* expectedHeader in expectedHeaders) {
|
|
||||||
if ([ignoredHeaders containsObject:expectedHeader]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
NSString* expectedValue = [expectedHeaders objectForKey:expectedHeader];
|
|
||||||
NSString* actualValue = [actualHeaders objectForKey:expectedHeader];
|
|
||||||
if (![actualValue isEqualToString:expectedValue]) {
|
|
||||||
_LogResult(@" Header '%@' not matching:\n Expected: \"%@\"\n Actual: \"%@\"", expectedHeader, expectedValue, actualValue);
|
|
||||||
success = NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (NSString* actualHeader in actualHeaders) {
|
|
||||||
if (![expectedHeaders objectForKey:actualHeader]) {
|
|
||||||
_LogResult(@" Header '%@' not matching:\n Expected: \"%@\"\n Actual: \"%@\"", actualHeader, nil, [actualHeaders objectForKey:actualHeader]);
|
|
||||||
success = NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSData* expectedBody = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyBody(expectedResponse));
|
|
||||||
NSData* actualBody = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyBody(actualResponse));
|
|
||||||
if (![actualBody isEqualToData:expectedBody]) {
|
|
||||||
_LogResult(@" Bodies not matching:\n Expected: %lu bytes\n Actual: %lu bytes", (unsigned long)expectedBody.length, (unsigned long)actualBody.length);
|
|
||||||
success = NO;
|
|
||||||
#if !TARGET_OS_IPHONE
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (GCDWebServerIsTextContentType([expectedHeaders objectForKey:@"Content-Type"])) {
|
|
||||||
NSString* expectedPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]];
|
|
||||||
NSString* actualPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]];
|
|
||||||
if ([expectedBody writeToFile:expectedPath atomically:YES] && [actualBody writeToFile:actualPath atomically:YES]) {
|
|
||||||
NSTask* task = [[NSTask alloc] init];
|
|
||||||
[task setLaunchPath:@"/usr/bin/opendiff"];
|
|
||||||
[task setArguments:@[expectedPath, actualPath]];
|
|
||||||
[task launch];
|
|
||||||
ARC_RELEASE(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRelease(actualResponse);
|
|
||||||
}
|
|
||||||
CFRelease(expectedResponse);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DNOT_REACHED();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CFRelease(request);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DNOT_REACHED();
|
|
||||||
}
|
|
||||||
_LogResult(@"");
|
|
||||||
if (!success) {
|
|
||||||
++result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[self stop];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GCDWebServer (Handlers)
|
@implementation GCDWebServer (Handlers)
|
||||||
@ -777,3 +594,186 @@ static void _LogResult(NSString* format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
|
|
||||||
|
@implementation GCDWebServer (Testing)
|
||||||
|
|
||||||
|
- (void)setRecordingEnabled:(BOOL)flag {
|
||||||
|
_recording = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isRecordingEnabled {
|
||||||
|
return _recording;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFHTTPMessageRef _CreateHTTPMessageFromData(NSData* data, BOOL isRequest) {
|
||||||
|
CFHTTPMessageRef message = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, isRequest);
|
||||||
|
if (CFHTTPMessageAppendBytes(message, data.bytes, data.length)) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
CFRelease(message);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFHTTPMessageRef _CreateHTTPMessageFromPerformingRequest(NSData* inData, NSUInteger port) {
|
||||||
|
CFHTTPMessageRef response = NULL;
|
||||||
|
int httpSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (httpSocket > 0) {
|
||||||
|
struct sockaddr_in addr4;
|
||||||
|
bzero(&addr4, sizeof(addr4));
|
||||||
|
addr4.sin_len = sizeof(port);
|
||||||
|
addr4.sin_family = AF_INET;
|
||||||
|
addr4.sin_port = htons(8080);
|
||||||
|
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
if (connect(httpSocket, (void*)&addr4, sizeof(addr4)) == 0) {
|
||||||
|
if (write(httpSocket, inData.bytes, inData.length) == (ssize_t)inData.length) {
|
||||||
|
NSMutableData* outData = [[NSMutableData alloc] initWithLength:(256 * 1024)];
|
||||||
|
NSUInteger length = 0;
|
||||||
|
while (1) {
|
||||||
|
ssize_t result = read(httpSocket, (char*)outData.mutableBytes + length, outData.length - length);
|
||||||
|
if (result < 0) {
|
||||||
|
length = NSNotFound;
|
||||||
|
break;
|
||||||
|
} else if (result == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
length += result;
|
||||||
|
if (length >= outData.length) {
|
||||||
|
outData.length = 2 * outData.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (length != NSNotFound) {
|
||||||
|
outData.length = length;
|
||||||
|
response = _CreateHTTPMessageFromData(outData, NO);
|
||||||
|
} else {
|
||||||
|
DNOT_REACHED();
|
||||||
|
}
|
||||||
|
ARC_RELEASE(outData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(httpSocket);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _LogResult(NSString* format, ...) {
|
||||||
|
va_list arguments;
|
||||||
|
va_start(arguments, format);
|
||||||
|
NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments];
|
||||||
|
va_end(arguments);
|
||||||
|
fprintf(stdout, "%s\n", [message UTF8String]);
|
||||||
|
ARC_RELEASE(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInteger)runTestsInDirectory:(NSString*)path withPort:(NSUInteger)port {
|
||||||
|
NSArray* ignoredHeaders = @[@"Date", @"Etag"]; // Dates are always different by definition and ETags depend on file system node IDs
|
||||||
|
NSInteger result = -1;
|
||||||
|
if ([self startWithPort:port bonjourName:nil]) {
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
|
||||||
|
for (NSString* requestFile in files) {
|
||||||
|
if (![requestFile hasSuffix:@".request"]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
@autoreleasepool {
|
||||||
|
NSString* index = [[requestFile componentsSeparatedByString:@"-"] firstObject];
|
||||||
|
BOOL success = NO;
|
||||||
|
NSData* requestData = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:requestFile]];
|
||||||
|
if (requestData) {
|
||||||
|
CFHTTPMessageRef request = _CreateHTTPMessageFromData(requestData, YES);
|
||||||
|
if (request) {
|
||||||
|
NSString* requestMethod = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestMethod(request));
|
||||||
|
NSURL* requestURL = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestURL(request));
|
||||||
|
_LogResult(@"[%i] %@ %@", (int)[index integerValue], requestMethod, requestURL.path);
|
||||||
|
NSString* prefix = [index stringByAppendingString:@"-"];
|
||||||
|
for (NSString* responseFile in files) {
|
||||||
|
if ([responseFile hasPrefix:prefix] && [responseFile hasSuffix:@".response"]) {
|
||||||
|
NSData* responseData = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:responseFile]];
|
||||||
|
if (responseData) {
|
||||||
|
CFHTTPMessageRef expectedResponse = _CreateHTTPMessageFromData(responseData, NO);
|
||||||
|
if (expectedResponse) {
|
||||||
|
CFHTTPMessageRef actualResponse = _CreateHTTPMessageFromPerformingRequest(requestData, port);
|
||||||
|
if (actualResponse) {
|
||||||
|
success = YES;
|
||||||
|
|
||||||
|
CFIndex expectedStatusCode = CFHTTPMessageGetResponseStatusCode(expectedResponse);
|
||||||
|
CFIndex actualStatusCode = CFHTTPMessageGetResponseStatusCode(actualResponse);
|
||||||
|
if (actualStatusCode != expectedStatusCode) {
|
||||||
|
_LogResult(@" Status code not matching:\n Expected: %i\n Actual: %i", (int)expectedStatusCode, (int)actualStatusCode);
|
||||||
|
success = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDictionary* expectedHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(expectedResponse));
|
||||||
|
NSDictionary* actualHeaders = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyAllHeaderFields(actualResponse));
|
||||||
|
for (NSString* expectedHeader in expectedHeaders) {
|
||||||
|
if ([ignoredHeaders containsObject:expectedHeader]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NSString* expectedValue = [expectedHeaders objectForKey:expectedHeader];
|
||||||
|
NSString* actualValue = [actualHeaders objectForKey:expectedHeader];
|
||||||
|
if (![actualValue isEqualToString:expectedValue]) {
|
||||||
|
_LogResult(@" Header '%@' not matching:\n Expected: \"%@\"\n Actual: \"%@\"", expectedHeader, expectedValue, actualValue);
|
||||||
|
success = NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (NSString* actualHeader in actualHeaders) {
|
||||||
|
if (![expectedHeaders objectForKey:actualHeader]) {
|
||||||
|
_LogResult(@" Header '%@' not matching:\n Expected: \"%@\"\n Actual: \"%@\"", actualHeader, nil, [actualHeaders objectForKey:actualHeader]);
|
||||||
|
success = NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSData* expectedBody = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyBody(expectedResponse));
|
||||||
|
NSData* actualBody = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyBody(actualResponse));
|
||||||
|
if (![actualBody isEqualToData:expectedBody]) {
|
||||||
|
_LogResult(@" Bodies not matching:\n Expected: %lu bytes\n Actual: %lu bytes", (unsigned long)expectedBody.length, (unsigned long)actualBody.length);
|
||||||
|
success = NO;
|
||||||
|
#if !TARGET_OS_IPHONE
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (GCDWebServerIsTextContentType([expectedHeaders objectForKey:@"Content-Type"])) {
|
||||||
|
NSString* expectedPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]];
|
||||||
|
NSString* actualPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[[NSProcessInfo processInfo] globallyUniqueString] stringByAppendingPathExtension:@"txt"]];
|
||||||
|
if ([expectedBody writeToFile:expectedPath atomically:YES] && [actualBody writeToFile:actualPath atomically:YES]) {
|
||||||
|
NSTask* task = [[NSTask alloc] init];
|
||||||
|
[task setLaunchPath:@"/usr/bin/opendiff"];
|
||||||
|
[task setArguments:@[expectedPath, actualPath]];
|
||||||
|
[task launch];
|
||||||
|
ARC_RELEASE(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(actualResponse);
|
||||||
|
}
|
||||||
|
CFRelease(expectedResponse);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DNOT_REACHED();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CFRelease(request);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DNOT_REACHED();
|
||||||
|
}
|
||||||
|
_LogResult(@"");
|
||||||
|
if (!success) {
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[self stop];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#import <TargetConditionals.h>
|
#import <TargetConditionals.h>
|
||||||
#import <netdb.h>
|
#import <netdb.h>
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
#import <libkern/OSAtomic.h>
|
#import <libkern/OSAtomic.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ static NSData* _CRLFData = nil;
|
|||||||
static NSData* _CRLFCRLFData = nil;
|
static NSData* _CRLFCRLFData = nil;
|
||||||
static NSData* _continueData = nil;
|
static NSData* _continueData = nil;
|
||||||
static NSData* _lastChunkData = nil;
|
static NSData* _lastChunkData = nil;
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
static int32_t _connectionCounter = 0;
|
static int32_t _connectionCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ static int32_t _connectionCounter = 0;
|
|||||||
NSInteger _statusCode;
|
NSInteger _statusCode;
|
||||||
|
|
||||||
BOOL _opened;
|
BOOL _opened;
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
NSUInteger _connectionIndex;
|
NSUInteger _connectionIndex;
|
||||||
NSString* _requestPath;
|
NSString* _requestPath;
|
||||||
int _requestFD;
|
int _requestFD;
|
||||||
@ -93,7 +93,7 @@ static int32_t _connectionCounter = 0;
|
|||||||
LOG_DEBUG(@"Connection received %zu bytes on socket %i", size, _socket);
|
LOG_DEBUG(@"Connection received %zu bytes on socket %i", size, _socket);
|
||||||
_bytesRead += size;
|
_bytesRead += size;
|
||||||
[self didUpdateBytesRead];
|
[self didUpdateBytesRead];
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
if (_requestFD > 0) {
|
if (_requestFD > 0) {
|
||||||
bool success = dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) {
|
bool success = dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) {
|
||||||
return (write(_requestFD, chunkBytes, chunkSize) == (ssize_t)chunkSize);
|
return (write(_requestFD, chunkBytes, chunkSize) == (ssize_t)chunkSize);
|
||||||
@ -291,7 +291,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
|
|
||||||
- (void)_writeBuffer:(dispatch_data_t)buffer withCompletionBlock:(WriteBufferCompletionBlock)block {
|
- (void)_writeBuffer:(dispatch_data_t)buffer withCompletionBlock:(WriteBufferCompletionBlock)block {
|
||||||
size_t size = dispatch_data_get_size(buffer);
|
size_t size = dispatch_data_get_size(buffer);
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
ARC_DISPATCH_RETAIN(buffer);
|
ARC_DISPATCH_RETAIN(buffer);
|
||||||
#endif
|
#endif
|
||||||
dispatch_write(_socket, buffer, kGCDWebServerGCDQueue, ^(dispatch_data_t data, int error) {
|
dispatch_write(_socket, buffer, kGCDWebServerGCDQueue, ^(dispatch_data_t data, int error) {
|
||||||
@ -302,7 +302,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
LOG_DEBUG(@"Connection sent %zu bytes on socket %i", size, _socket);
|
LOG_DEBUG(@"Connection sent %zu bytes on socket %i", size, _socket);
|
||||||
_bytesWritten += size;
|
_bytesWritten += size;
|
||||||
[self didUpdateBytesWritten];
|
[self didUpdateBytesWritten];
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
if (_responseFD > 0) {
|
if (_responseFD > 0) {
|
||||||
bool success = dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) {
|
bool success = dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t chunkOffset, const void* chunkBytes, size_t chunkSize) {
|
||||||
return (write(_responseFD, chunkBytes, chunkSize) == (ssize_t)chunkSize);
|
return (write(_responseFD, chunkBytes, chunkSize) == (ssize_t)chunkSize);
|
||||||
@ -320,7 +320,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
|||||||
block(NO);
|
block(NO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
ARC_DISPATCH_RELEASE(buffer);
|
ARC_DISPATCH_RELEASE(buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -715,7 +715,7 @@ static NSString* _StringFromAddressData(NSData* data) {
|
|||||||
}
|
}
|
||||||
ARC_RELEASE(_response);
|
ARC_RELEASE(_response);
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
ARC_RELEASE(_requestPath);
|
ARC_RELEASE(_requestPath);
|
||||||
ARC_RELEASE(_responsePath);
|
ARC_RELEASE(_responsePath);
|
||||||
#endif
|
#endif
|
||||||
@ -728,7 +728,7 @@ static NSString* _StringFromAddressData(NSData* data) {
|
|||||||
@implementation GCDWebServerConnection (Subclassing)
|
@implementation GCDWebServerConnection (Subclassing)
|
||||||
|
|
||||||
- (BOOL)open {
|
- (BOOL)open {
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
if (_server.recordingEnabled) {
|
if (_server.recordingEnabled) {
|
||||||
_connectionIndex = OSAtomicIncrement32(&_connectionCounter);
|
_connectionIndex = OSAtomicIncrement32(&_connectionCounter);
|
||||||
|
|
||||||
@ -804,7 +804,7 @@ static inline BOOL _CompareResources(NSString* responseETag, NSString* requestET
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)close {
|
- (void)close {
|
||||||
#if !TARGET_OS_IPHONE
|
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
if (_requestPath) {
|
if (_requestPath) {
|
||||||
BOOL success = NO;
|
BOOL success = NO;
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
|
|||||||
@ -39,6 +39,10 @@
|
|||||||
|
|
||||||
#import "GCDWebUploader.h"
|
#import "GCDWebUploader.h"
|
||||||
|
|
||||||
|
#ifndef __GCDWEBSERVER_ENABLE_TESTING__
|
||||||
|
#error __GCDWEBSERVER_ENABLE_TESTING__ must be defined
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kMode_WebServer = 0,
|
kMode_WebServer = 0,
|
||||||
kMode_HTMLPage,
|
kMode_HTMLPage,
|
||||||
|
|||||||
Reference in New Issue
Block a user