Эх сурвалжийг харах

Isolated all testing code with __GCDWEBSERVER_ENABLE_TESTING__

Pierre-Olivier Latour 11 жил өмнө
parent
commit
016153f900

+ 9 - 4
GCDWebServer/Core/GCDWebServer.h

@@ -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* bonjourServerURL;  // Only non-nil if server is running and Bonjour registration is active
 #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)
 #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
 
 @interface GCDWebServer (Handlers)
@@ -94,3 +90,12 @@ typedef GCDWebServerResponse* (^GCDWebServerProcessBlock)(GCDWebServerRequest* r
 - (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
 - (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
 @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

+ 184 - 184
GCDWebServer/Core/GCDWebServer.m

@@ -49,7 +49,7 @@
   NSUInteger _port;
   dispatch_source_t _source;
   CFNetServiceRef _service;
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
   BOOL _recording;
 #endif
 }
@@ -334,18 +334,6 @@ static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* er
 
 @implementation GCDWebServer (Extensions)
 
-#if !TARGET_OS_IPHONE
-
-- (void)setRecordingEnabled:(BOOL)flag {
-  _recording = flag;
-}
-
-- (BOOL)isRecordingEnabled {
-  return _recording;
-}
-
-#endif
-
 - (NSURL*)serverURL {
   if (_source) {
     NSString* ipAddress = GCDWebServerGetPrimaryIPv4Address();
@@ -395,177 +383,6 @@ static void _NetServiceClientCallBack(CFNetServiceRef service, CFStreamError* er
 
 #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
 
 @implementation GCDWebServer (Handlers)
@@ -777,3 +594,186 @@ static void _LogResult(NSString* format, ...) {
 }
 
 @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

+ 10 - 10
GCDWebServer/Core/GCDWebServerConnection.m

@@ -27,7 +27,7 @@
 
 #import <TargetConditionals.h>
 #import <netdb.h>
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 #import <libkern/OSAtomic.h>
 #endif
 
@@ -49,7 +49,7 @@ static NSData* _CRLFData = nil;
 static NSData* _CRLFCRLFData = nil;
 static NSData* _continueData = nil;
 static NSData* _lastChunkData = nil;
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
 static int32_t _connectionCounter = 0;
 #endif
 
@@ -71,7 +71,7 @@ static int32_t _connectionCounter = 0;
   NSInteger _statusCode;
   
   BOOL _opened;
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
   NSUInteger _connectionIndex;
   NSString* _requestPath;
   int _requestFD;
@@ -93,7 +93,7 @@ static int32_t _connectionCounter = 0;
           LOG_DEBUG(@"Connection received %zu bytes on socket %i", size, _socket);
           _bytesRead += size;
           [self didUpdateBytesRead];
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
           if (_requestFD > 0) {
             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);
@@ -291,7 +291,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
 
 - (void)_writeBuffer:(dispatch_data_t)buffer withCompletionBlock:(WriteBufferCompletionBlock)block {
   size_t size = dispatch_data_get_size(buffer);
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
   ARC_DISPATCH_RETAIN(buffer);
 #endif
   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);
         _bytesWritten += size;
         [self didUpdateBytesWritten];
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
         if (_responseFD > 0) {
           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);
@@ -320,7 +320,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
         block(NO);
       }
     }
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
     ARC_DISPATCH_RELEASE(buffer);
 #endif
     
@@ -715,7 +715,7 @@ static NSString* _StringFromAddressData(NSData* data) {
   }
   ARC_RELEASE(_response);
   
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
   ARC_RELEASE(_requestPath);
   ARC_RELEASE(_responsePath);
 #endif
@@ -728,7 +728,7 @@ static NSString* _StringFromAddressData(NSData* data) {
 @implementation GCDWebServerConnection (Subclassing)
 
 - (BOOL)open {
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
   if (_server.recordingEnabled) {
     _connectionIndex = OSAtomicIncrement32(&_connectionCounter);
     
@@ -804,7 +804,7 @@ static inline BOOL _CompareResources(NSString* responseETag, NSString* requestET
 }
 
 - (void)close {
-#if !TARGET_OS_IPHONE
+#ifdef __GCDWEBSERVER_ENABLE_TESTING__
   if (_requestPath) {
     BOOL success = NO;
     NSError* error = nil;

+ 4 - 0
Mac/main.m

@@ -39,6 +39,10 @@
 
 #import "GCDWebUploader.h"
 
+#ifndef __GCDWEBSERVER_ENABLE_TESTING__
+#error __GCDWEBSERVER_ENABLE_TESTING__ must be defined
+#endif
+
 typedef enum {
   kMode_WebServer = 0,
   kMode_HTMLPage,