Project import
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5011142
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+OCMock
+======
+
+OCMock is an Objective-C implementation of mock objects. 
+
+Github is used to store and manage the source code. 
+
+For downloads, documentation, and support please visit [ocmock.org][].  
+
+[![Build Status](https://travis-ci.org/erikdoe/ocmock.png?branch=master)](https://travis-ci.org/erikdoe/ocmock)
+
+  [ocmock.org]: http://ocmock.org/
diff --git a/Source/License.txt b/Source/License.txt
new file mode 100644
index 0000000..f433b1a
--- /dev/null
+++ b/Source/License.txt
@@ -0,0 +1,177 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/Source/OCMock/NSInvocation+OCMAdditions.h b/Source/OCMock/NSInvocation+OCMAdditions.h
new file mode 100644
index 0000000..894f632
--- /dev/null
+++ b/Source/OCMock/NSInvocation+OCMAdditions.h
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2006-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSInvocation(OCMAdditions)
+
+- (BOOL)hasCharPointerArgument;
+
+- (id)getArgumentAtIndexAsObject:(NSInteger)argIndex;
+
+- (NSString *)invocationDescription;
+
+- (NSString *)argumentDescriptionAtIndex:(NSInteger)argIndex;
+
+- (NSString *)objectDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)charDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)unsignedCharDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)intDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)unsignedIntDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)shortDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)unsignedShortDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)longDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)unsignedLongDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)longLongDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)unsignedLongLongDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)doubleDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)floatDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)structDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)pointerDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)cStringDescriptionAtIndex:(NSInteger)anInt;
+- (NSString *)selectorDescriptionAtIndex:(NSInteger)anInt;
+
+@end
diff --git a/Source/OCMock/NSInvocation+OCMAdditions.m b/Source/OCMock/NSInvocation+OCMAdditions.m
new file mode 100644
index 0000000..94342c6
--- /dev/null
+++ b/Source/OCMock/NSInvocation+OCMAdditions.m
@@ -0,0 +1,380 @@
+/*
+ *  Copyright (c) 2006-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "NSInvocation+OCMAdditions.h"
+#import "OCMFunctions.h"
+
+
+@implementation NSInvocation(OCMAdditions)
+
+- (BOOL)hasCharPointerArgument
+{
+    NSMethodSignature *signature = [self methodSignature];
+    for(NSUInteger i = 0; i < [signature numberOfArguments]; i++)
+    {
+        const char *argType = OCMTypeWithoutQualifiers([signature getArgumentTypeAtIndex:i]);
+        if(strcmp(argType, "*") == 0)
+            return YES;
+    }
+    return NO;
+}
+
+
+- (id)getArgumentAtIndexAsObject:(NSInteger)argIndex
+{
+	const char *argType = OCMTypeWithoutQualifiers([[self methodSignature] getArgumentTypeAtIndex:(NSUInteger)argIndex]);
+
+	if((strlen(argType) > 1) && (strchr("{^", argType[0]) == NULL) && (strcmp("@?", argType) != 0))
+		[NSException raise:NSInvalidArgumentException format:@"Cannot handle argument type '%s'.", argType];
+
+    if(OCMIsObjectType(argType))
+    {
+        id value;
+     	[self getArgument:&value atIndex:argIndex];
+     	return value;
+    }
+
+	switch(argType[0])
+	{
+		case ':':
+ 		{
+ 			SEL s = (SEL)0;
+ 			[self getArgument:&s atIndex:argIndex];
+            return [NSValue valueWithBytes:&s objCType:":"];
+ 		}
+		case 'i': 
+		{
+			int value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 's':
+		{
+			short value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'l':
+		{
+			long value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'q':
+		{
+			long long value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'c':
+		{
+			char value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'C':
+		{
+			unsigned char value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'I':
+		{
+			unsigned int value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'S':
+		{
+			unsigned short value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'L':
+		{
+			unsigned long value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'Q':
+		{
+			unsigned long long value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'f':
+		{
+			float value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'd':
+		{
+			double value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}	
+		case 'D':
+		{
+			long double value;
+			[self getArgument:&value atIndex:argIndex];
+			return [NSValue valueWithBytes:&value objCType:@encode(typeof(value))];
+		}
+		case 'B':
+		{
+			bool value;
+			[self getArgument:&value atIndex:argIndex];
+			return @(value);
+		}
+		case '^':
+        case '*':
+        {
+            void *value = NULL;
+            [self getArgument:&value atIndex:argIndex];
+            return [NSValue valueWithPointer:value];
+        }
+		case '{': // structure
+		{
+			NSUInteger argSize;
+			NSGetSizeAndAlignment([[self methodSignature] getArgumentTypeAtIndex:(NSUInteger)argIndex], &argSize, NULL);
+			if(argSize == 0) // TODO: Can this happen? Is frameLength a good choice in that case?
+                argSize = [[self methodSignature] frameLength];
+			NSMutableData *argumentData = [[[NSMutableData alloc] initWithLength:argSize] autorelease];
+			[self getArgument:[argumentData mutableBytes] atIndex:argIndex];
+			return [NSValue valueWithBytes:[argumentData bytes] objCType:argType];
+		}       
+			
+	}
+	[NSException raise:NSInvalidArgumentException format:@"Argument type '%s' not supported", argType];
+	return nil;
+}
+
+- (NSString *)invocationDescription
+{
+	NSMethodSignature *methodSignature = [self methodSignature];
+	NSUInteger numberOfArgs = [methodSignature numberOfArguments];
+	
+	if (numberOfArgs == 2)
+		return NSStringFromSelector([self selector]);
+	
+	NSArray *selectorParts = [NSStringFromSelector([self selector]) componentsSeparatedByString:@":"];
+	NSMutableString *description = [[NSMutableString alloc] init];
+	NSUInteger i;
+	for(i = 2; i < numberOfArgs; i++)
+	{
+		[description appendFormat:@"%@%@:", (i > 2 ? @" " : @""), [selectorParts objectAtIndex:(i - 2)]];
+		[description appendString:[self argumentDescriptionAtIndex:(NSInteger)i]];
+	}
+	
+	return [description autorelease];
+}
+
+- (NSString *)argumentDescriptionAtIndex:(NSInteger)argIndex
+{
+	const char *argType = OCMTypeWithoutQualifiers([[self methodSignature] getArgumentTypeAtIndex:(NSUInteger)argIndex]);
+
+	switch(*argType)
+	{
+		case '@':	return [self objectDescriptionAtIndex:argIndex];
+		case 'B':	return [self boolDescriptionAtIndex:argIndex];
+		case 'c':	return [self charDescriptionAtIndex:argIndex];
+		case 'C':	return [self unsignedCharDescriptionAtIndex:argIndex];
+		case 'i':	return [self intDescriptionAtIndex:argIndex];
+		case 'I':	return [self unsignedIntDescriptionAtIndex:argIndex];
+		case 's':	return [self shortDescriptionAtIndex:argIndex];
+		case 'S':	return [self unsignedShortDescriptionAtIndex:argIndex];
+		case 'l':	return [self longDescriptionAtIndex:argIndex];
+		case 'L':	return [self unsignedLongDescriptionAtIndex:argIndex];
+		case 'q':	return [self longLongDescriptionAtIndex:argIndex];
+		case 'Q':	return [self unsignedLongLongDescriptionAtIndex:argIndex];
+		case 'd':	return [self doubleDescriptionAtIndex:argIndex];
+		case 'f':	return [self floatDescriptionAtIndex:argIndex];
+		case 'D':	return [self longDoubleDescriptionAtIndex:argIndex];
+		case '{':	return [self structDescriptionAtIndex:argIndex];
+		case '^':	return [self pointerDescriptionAtIndex:argIndex];
+		case '*':	return [self cStringDescriptionAtIndex:argIndex];
+		case ':':	return [self selectorDescriptionAtIndex:argIndex];
+		default:	return [@"<??" stringByAppendingString:@">"];  // avoid confusion with trigraphs...
+	}
+	
+}
+
+
+- (NSString *)objectDescriptionAtIndex:(NSInteger)anInt
+{
+	id object;
+	
+	[self getArgument:&object atIndex:anInt];
+	if (object == nil)
+		return @"nil";
+	else if(![object isProxy] && [object isKindOfClass:[NSString class]])
+		return [NSString stringWithFormat:@"@\"%@\"", [object description]];
+	else
+		// The description cannot be nil, if it is then replace it
+		return [object description] ?: @"<nil description>";
+}
+
+- (NSString *)boolDescriptionAtIndex:(NSInteger)anInt
+{
+	bool value;
+	[self getArgument:&value atIndex:anInt];
+	return value? @"YES" : @"NO";
+}
+
+- (NSString *)charDescriptionAtIndex:(NSInteger)anInt
+{
+	unsigned char buffer[128];
+	memset(buffer, 0x0, 128);
+	
+	[self getArgument:&buffer atIndex:anInt];
+	
+	// If there's only one character in the buffer, and it's 0 or 1, then we have a BOOL
+	if (buffer[1] == '\0' && (buffer[0] == 0 || buffer[0] == 1))
+		return (buffer[0] == 1 ? @"YES" : @"NO");
+	else
+		return [NSString stringWithFormat:@"'%c'", *buffer];
+}
+
+- (NSString *)unsignedCharDescriptionAtIndex:(NSInteger)anInt
+{
+	unsigned char buffer[128];
+	memset(buffer, 0x0, 128);
+	
+	[self getArgument:&buffer atIndex:anInt];
+	return [NSString stringWithFormat:@"'%c'", *buffer];
+}
+
+- (NSString *)intDescriptionAtIndex:(NSInteger)anInt
+{
+	int intValue;
+	
+	[self getArgument:&intValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%d", intValue];
+}
+
+- (NSString *)unsignedIntDescriptionAtIndex:(NSInteger)anInt
+{
+	unsigned int intValue;
+	
+	[self getArgument:&intValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%d", intValue];
+}
+
+- (NSString *)shortDescriptionAtIndex:(NSInteger)anInt
+{
+	short shortValue;
+	
+	[self getArgument:&shortValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%hi", shortValue];
+}
+
+- (NSString *)unsignedShortDescriptionAtIndex:(NSInteger)anInt
+{
+	unsigned short shortValue;
+	
+	[self getArgument:&shortValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%hu", shortValue];
+}
+
+- (NSString *)longDescriptionAtIndex:(NSInteger)anInt
+{
+	long longValue;
+	
+	[self getArgument:&longValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%ld", longValue];
+}
+
+- (NSString *)unsignedLongDescriptionAtIndex:(NSInteger)anInt
+{
+	unsigned long longValue;
+	
+	[self getArgument:&longValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%lu", longValue];
+}
+
+- (NSString *)longLongDescriptionAtIndex:(NSInteger)anInt
+{
+	long long longLongValue;
+	
+	[self getArgument:&longLongValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%qi", longLongValue];
+}
+
+- (NSString *)unsignedLongLongDescriptionAtIndex:(NSInteger)anInt
+{
+	unsigned long long longLongValue;
+	
+	[self getArgument:&longLongValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%qu", longLongValue];
+}
+
+- (NSString *)doubleDescriptionAtIndex:(NSInteger)anInt
+{
+	double doubleValue;
+	
+	[self getArgument:&doubleValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%f", doubleValue];
+}
+
+- (NSString *)floatDescriptionAtIndex:(NSInteger)anInt
+{
+	float floatValue;
+	
+	[self getArgument:&floatValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%f", floatValue];
+}
+
+- (NSString *)longDoubleDescriptionAtIndex:(NSInteger)anInt
+{
+	long double longDoubleValue;
+	
+	[self getArgument:&longDoubleValue atIndex:anInt];
+	return [NSString stringWithFormat:@"%Lf", longDoubleValue];
+}
+
+- (NSString *)structDescriptionAtIndex:(NSInteger)anInt
+{
+    return [NSString stringWithFormat:@"(%@)", [[self getArgumentAtIndexAsObject:anInt] description]];
+}
+
+- (NSString *)pointerDescriptionAtIndex:(NSInteger)anInt
+{
+	void *buffer;
+	
+	[self getArgument:&buffer atIndex:anInt];
+	return [NSString stringWithFormat:@"%p", buffer];
+}
+
+- (NSString *)cStringDescriptionAtIndex:(NSInteger)anInt
+{
+	char buffer[104];
+	char *cStringPtr;
+	
+	[self getArgument:&cStringPtr atIndex:anInt];
+	strncpy(buffer, cStringPtr, 100);
+    strcpy(buffer + 100, "...");
+	return [NSString stringWithFormat:@"\"%s\"", buffer];
+}
+
+- (NSString *)selectorDescriptionAtIndex:(NSInteger)anInt
+{
+	SEL selectorValue;
+	
+	[self getArgument:&selectorValue atIndex:anInt];
+	return [NSString stringWithFormat:@"@selector(%@)", NSStringFromSelector(selectorValue)];
+}
+
+@end
diff --git a/Source/OCMock/NSMethodSignature+OCMAdditions.h b/Source/OCMock/NSMethodSignature+OCMAdditions.h
new file mode 100644
index 0000000..b183df9
--- /dev/null
+++ b/Source/OCMock/NSMethodSignature+OCMAdditions.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSMethodSignature(PrivateAPI)
+
++ (id)signatureWithObjCTypes:(const char *)types;
+
+@end
+
+@interface NSMethodSignature(OCMAdditions)
+
+- (BOOL)usesSpecialStructureReturn;
+- (NSString *)fullTypeString;
+- (const char *)fullObjCTypes;
+
+@end
diff --git a/Source/OCMock/NSMethodSignature+OCMAdditions.m b/Source/OCMock/NSMethodSignature+OCMAdditions.m
new file mode 100644
index 0000000..d60590d
--- /dev/null
+++ b/Source/OCMock/NSMethodSignature+OCMAdditions.m
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "NSMethodSignature+OCMAdditions.h"
+#import "OCMFunctions.h"
+#import <objc/runtime.h>
+
+
+@implementation NSMethodSignature(OCMAdditions)
+
+- (BOOL)usesSpecialStructureReturn
+{
+    const char *types = OCMTypeWithoutQualifiers([self methodReturnType]);
+
+    if((types == NULL) || (types[0] != '{'))
+        return NO;
+
+    /* In some cases structures are returned by ref. The rules are complex and depend on the
+       architecture, see:
+
+       http://sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html
+       http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/000-Introduction/introduction.html
+       https://github.com/atgreen/libffi/blob/master/src/x86/ffi64.c
+       http://www.uclibc.org/docs/psABI-x86_64.pdf
+       http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf
+
+       NSMethodSignature knows the details but has no API to return it, though it is in
+       the debugDescription. Horribly kludgy.
+    */
+    NSRange range = [[self debugDescription] rangeOfString:@"is special struct return? YES"];
+    return range.length > 0;
+}
+
+- (NSString *)fullTypeString
+{
+    NSMutableString *typeString = [NSMutableString string];
+    [typeString appendFormat:@"%s", [self methodReturnType]];
+    for (NSUInteger i=0; i<[self numberOfArguments]; i++)
+        [typeString appendFormat:@"%s", [self getArgumentTypeAtIndex:i]];
+    return typeString;
+}
+
+- (const char *)fullObjCTypes
+{
+    return [[self fullTypeString] UTF8String];
+}
+
+@end
diff --git a/Source/OCMock/NSNotificationCenter+OCMAdditions.h b/Source/OCMock/NSNotificationCenter+OCMAdditions.h
new file mode 100644
index 0000000..c20a9c2
--- /dev/null
+++ b/Source/OCMock/NSNotificationCenter+OCMAdditions.h
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class OCObserverMockObject;
+
+
+@interface NSNotificationCenter(OCMAdditions)
+
+- (void)addMockObserver:(OCObserverMockObject *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender;
+
+@end
diff --git a/Source/OCMock/NSNotificationCenter+OCMAdditions.m b/Source/OCMock/NSNotificationCenter+OCMAdditions.m
new file mode 100644
index 0000000..14ff7f7
--- /dev/null
+++ b/Source/OCMock/NSNotificationCenter+OCMAdditions.m
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "NSNotificationCenter+OCMAdditions.h"
+#import "OCObserverMockObject.h"
+
+
+@implementation NSNotificationCenter(OCMAdditions)
+
+- (void)addMockObserver:(OCObserverMockObject *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender
+{
+    [notificationObserver autoRemoveFromCenter:self];
+	[self addObserver:notificationObserver selector:@selector(handleNotification:) name:notificationName object:notificationSender];
+}
+
+@end
diff --git a/Source/OCMock/NSObject+OCMAdditions.h b/Source/OCMock/NSObject+OCMAdditions.h
new file mode 100644
index 0000000..f7b9c5c
--- /dev/null
+++ b/Source/OCMock/NSObject+OCMAdditions.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (c) 2013-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSObject(OCMAdditions)
+
++ (IMP)instanceMethodForwarderForSelector:(SEL)aSelector;
++ (void)enumerateMethodsInClass:(Class)aClass usingBlock:(void (^)(Class cls, SEL sel))aBlock;
+
+@end
diff --git a/Source/OCMock/NSObject+OCMAdditions.m b/Source/OCMock/NSObject+OCMAdditions.m
new file mode 100644
index 0000000..e4e0aaa
--- /dev/null
+++ b/Source/OCMock/NSObject+OCMAdditions.m
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "NSObject+OCMAdditions.h"
+#import "NSMethodSignature+OCMAdditions.h"
+#import <objc/runtime.h>
+
+@implementation NSObject(OCMAdditions)
+
+static NSMutableDictionary *_OCMReturnTypeCache;
+
++ (IMP)instanceMethodForwarderForSelector:(SEL)aSelector
+{
+    // use sel_registerName() and not @selector to avoid warning
+    SEL selectorWithNoImplementation = sel_registerName("methodWhichMustNotExist::::");
+
+#ifndef __arm64__
+    if(_OCMReturnTypeCache == nil)
+        _OCMReturnTypeCache = [[NSMutableDictionary alloc] init];
+
+    BOOL needsStructureReturn;
+    void *rawCacheKey[2] = { (void *)self, aSelector };
+    NSData *cacheKey = [NSData dataWithBytes:rawCacheKey length:sizeof(rawCacheKey)];
+    NSNumber *cachedValue = [_OCMReturnTypeCache objectForKey:cacheKey];
+
+    if(cachedValue == nil)
+    {
+        NSMethodSignature *sig = [self instanceMethodSignatureForSelector:aSelector];
+        needsStructureReturn = [sig usesSpecialStructureReturn];
+        [_OCMReturnTypeCache setObject:@(needsStructureReturn) forKey:cacheKey];
+    }
+    else
+    {
+        needsStructureReturn = [cachedValue boolValue];
+    }
+
+    if(needsStructureReturn)
+        return class_getMethodImplementation_stret([NSObject class], selectorWithNoImplementation);
+#endif
+    
+    return class_getMethodImplementation([NSObject class], selectorWithNoImplementation);
+}
+
+
++ (void)enumerateMethodsInClass:(Class)aClass usingBlock:(void (^)(Class cls, SEL sel))aBlock
+{
+    for(Class cls = aClass; cls != nil; cls = class_getSuperclass(cls))
+    {
+        Method *methodList = class_copyMethodList(cls, NULL);
+        if(methodList == NULL)
+            continue;
+
+        for(Method *mPtr = methodList; *mPtr != NULL; mPtr++)
+        {
+            SEL sel = method_getName(*mPtr);
+            aBlock(cls, sel);
+        }
+        free(methodList);
+    }
+}
+
+@end
diff --git a/Source/OCMock/NSValue+OCMAdditions.h b/Source/OCMock/NSValue+OCMAdditions.h
new file mode 100644
index 0000000..1b79a30
--- /dev/null
+++ b/Source/OCMock/NSValue+OCMAdditions.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSValue(OCMAdditions)
+
+- (BOOL)getBytes:(void *)outputBuf objCType:(const char *)targetType;
+
+@end
\ No newline at end of file
diff --git a/Source/OCMock/NSValue+OCMAdditions.m b/Source/OCMock/NSValue+OCMAdditions.m
new file mode 100644
index 0000000..59f9ad4
--- /dev/null
+++ b/Source/OCMock/NSValue+OCMAdditions.m
@@ -0,0 +1,107 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "NSValue+OCMAdditions.h"
+
+
+@implementation NSValue(OCMAdditions)
+
+static CFNumberType OCMNumberTypeForObjCType(const char *objcType)
+{
+    switch (objcType[0])
+    {
+        case 'c': return kCFNumberCharType;
+        case 'C': return kCFNumberCharType;
+        case 'B': return kCFNumberCharType;
+        case 's': return kCFNumberShortType;
+        case 'S': return kCFNumberShortType;
+        case 'i': return kCFNumberIntType;
+        case 'I': return kCFNumberIntType;
+        case 'l': return kCFNumberLongType;
+        case 'L': return kCFNumberLongType;
+        case 'q': return kCFNumberLongLongType;
+        case 'Q': return kCFNumberLongLongType;
+        case 'f': return kCFNumberFloatType;
+        case 'd': return kCFNumberDoubleType;
+        default:  return 0;
+    }
+}
+
+
+static NSNumber *OCMNumberForValue(NSValue *value)
+{
+#define CREATE_NUM(_type) ({ _type _v; [value getValue:&_v]; @(_v); })
+    switch([value objCType][0])
+    {
+        case 'c': return CREATE_NUM(char);
+        case 'C': return CREATE_NUM(unsigned char);
+        case 'B': return CREATE_NUM(bool);
+        case 's': return CREATE_NUM(short);
+        case 'S': return CREATE_NUM(unsigned short);
+        case 'i': return CREATE_NUM(int);
+        case 'I': return CREATE_NUM(unsigned int);
+        case 'l': return CREATE_NUM(long);
+        case 'L': return CREATE_NUM(unsigned long);
+        case 'q': return CREATE_NUM(long long);
+        case 'Q': return CREATE_NUM(unsigned long long);
+        case 'f': return CREATE_NUM(float);
+        case 'd': return CREATE_NUM(double);
+        default:  return nil;
+    }
+}
+
+
+- (BOOL)getBytes:(void *)outputBuf objCType:(const char *)targetType
+{
+    /*
+     * See if they are similar number types, and if we can convert losslessly between them.
+     * For the most part, we set things up to use CFNumberGetValue, which returns false if
+     * conversion will be lossy.
+     */
+    CFNumberType inputType = OCMNumberTypeForObjCType([self objCType]);
+    CFNumberType outputType = OCMNumberTypeForObjCType(targetType);
+
+    if(inputType == 0 || outputType == 0) // one or both are non-number types
+        return NO;
+
+    NSNumber *inputNumber = [self isKindOfClass:[NSNumber class]] ? (NSNumber *)self : OCMNumberForValue(self);
+
+    /*
+     * Due to some legacy, back-compatible requirements in CFNumber.c, CFNumberGetValue can return true for
+     * some conversions which should not be allowed (by reading source, conversions from integer types to
+     * 8-bit or 16-bit integer types).  So, check ourselves.
+     */
+    long long min;
+    long long max;
+    long long val = [inputNumber longLongValue];
+    switch(targetType[0])
+    {
+        case 'B':
+        case 'c': min =  CHAR_MIN; max =  CHAR_MAX; break;
+        case 'C': min =         0; max = UCHAR_MAX; break;
+        case 's': min =  SHRT_MIN; max =  SHRT_MAX; break;
+        case 'S': min =         0; max = USHRT_MAX; break;
+        default:  min = LLONG_MIN; max = LLONG_MAX; break;
+    }
+    if(val < min || val > max)
+        return NO;
+
+    /* Get the number, and return NO if the value was out of range or conversion was lossy */
+    return CFNumberGetValue((CFNumberRef)inputNumber, outputType, outputBuf);
+}
+
+
+@end
diff --git a/Source/OCMock/OCClassMockObject.h b/Source/OCMock/OCClassMockObject.h
new file mode 100644
index 0000000..18190c7
--- /dev/null
+++ b/Source/OCMock/OCClassMockObject.h
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2005-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <OCMock/OCMockObject.h>
+
+@interface OCClassMockObject : OCMockObject 
+{
+	Class               mockedClass;
+    Class               originalMetaClass;
+}
+
+- (id)initWithClass:(Class)aClass;
+
+- (Class)mockedClass;
+- (Class)mockObjectClass;  // since -class returns the mockedClass
+
+@end
diff --git a/Source/OCMock/OCClassMockObject.m b/Source/OCMock/OCClassMockObject.m
new file mode 100644
index 0000000..8ed24cb
--- /dev/null
+++ b/Source/OCMock/OCClassMockObject.m
@@ -0,0 +1,276 @@
+/*
+ *  Copyright (c) 2005-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import "OCClassMockObject.h"
+#import "NSObject+OCMAdditions.h"
+#import "OCMFunctions.h"
+#import "OCMInvocationStub.h"
+
+@implementation OCClassMockObject
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (id)initWithClass:(Class)aClass
+{
+	[super init];
+	mockedClass = aClass;
+    [self prepareClassForClassMethodMocking];
+	return self;
+}
+
+- (void)dealloc
+{
+	[self stopMocking];
+	[super dealloc];
+}
+
+- (NSString *)description
+{
+	return [NSString stringWithFormat:@"OCMockObject(%@)", NSStringFromClass(mockedClass)];
+}
+
+- (Class)mockedClass
+{
+	return mockedClass;
+}
+
+#pragma mark  Extending/overriding superclass behaviour
+
+- (void)stopMocking
+{
+    if(originalMetaClass != nil)
+        [self restoreMetaClass];
+    [super stopMocking];
+}
+
+- (void)restoreMetaClass
+{
+    OCMSetAssociatedMockForClass(nil, mockedClass);
+    OCMSetIsa(mockedClass, originalMetaClass);
+    originalMetaClass = nil;
+}
+
+- (void)addStub:(OCMInvocationStub *)aStub
+{
+    [super addStub:aStub];
+    if([aStub recordedAsClassMethod])
+        [self setupForwarderForClassMethodSelector:[[aStub recordedInvocation] selector]];
+}
+
+
+#pragma mark  Class method mocking
+
+- (void)prepareClassForClassMethodMocking
+{
+    /* haven't figured out how to work around runtime dependencies on NSString, so exclude it for now */
+    /* also weird: [[NSString class] isKindOfClass:[NSString class]] is false, hence the additional clause */
+    if([[mockedClass class] isKindOfClass:[NSString class]] || (mockedClass == [NSString class]))
+        return;
+
+    /* if there is another mock for this exact class, stop it */
+    id otherMock = OCMGetAssociatedMockForClass(mockedClass, NO);
+    if(otherMock != nil)
+        [otherMock restoreMetaClass];
+
+    OCMSetAssociatedMockForClass(self, mockedClass);
+
+    /* dynamically create a subclass and use its meta class as the meta class for the mocked class */
+    Class subclass = OCMCreateSubclass(mockedClass, mockedClass);
+    originalMetaClass = object_getClass(mockedClass);
+    id newMetaClass = object_getClass(subclass);
+    OCMSetIsa(mockedClass, OCMGetIsa(subclass));
+
+    /* point forwardInvocation: of the object to the implementation in the mock */
+    Method myForwardMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardInvocationForClassObject:));
+    IMP myForwardIMP = method_getImplementation(myForwardMethod);
+    class_addMethod(newMetaClass, @selector(forwardInvocation:), myForwardIMP, method_getTypeEncoding(myForwardMethod));
+
+    /* create a dummy initialize method */
+    Method myDummyInitializeMethod = class_getInstanceMethod([self mockObjectClass], @selector(initializeForClassObject));
+    const char *initializeTypes = method_getTypeEncoding(myDummyInitializeMethod);
+    IMP myDummyInitializeIMP = method_getImplementation(myDummyInitializeMethod);
+    class_addMethod(newMetaClass, @selector(initialize), myDummyInitializeIMP, initializeTypes);
+
+    /* adding forwarder for most class methods (instance methods on meta class) to allow for verify after run */
+    NSArray *methodBlackList = @[@"class", @"forwardingTargetForSelector:", @"methodSignatureForSelector:", @"forwardInvocation:", @"isBlock",
+            @"instanceMethodForwarderForSelector:", @"instanceMethodSignatureForSelector:"];
+    [NSObject enumerateMethodsInClass:originalMetaClass usingBlock:^(Class cls, SEL sel) {
+        if((cls == object_getClass([NSObject class])) || (cls == [NSObject class]) || (cls == object_getClass(cls)))
+            return;
+        NSString *className = NSStringFromClass(cls);
+        NSString *selName = NSStringFromSelector(sel);
+        if(([className hasPrefix:@"NS"] || [className hasPrefix:@"UI"]) &&
+           ([selName hasPrefix:@"_"] || [selName hasSuffix:@"_"]))
+            return;
+        if([methodBlackList containsObject:selName])
+            return;
+        @try
+        {
+            [self setupForwarderForClassMethodSelector:sel];
+        }
+        @catch(NSException *e)
+        {
+            // ignore for now
+        }
+    }];
+}
+
+- (void)setupForwarderForClassMethodSelector:(SEL)selector
+{
+    SEL aliasSelector = OCMAliasForOriginalSelector(selector);
+    if(class_getClassMethod(mockedClass, aliasSelector) != NULL)
+        return;
+
+    Method originalMethod = class_getClassMethod(mockedClass, selector);
+    IMP originalIMP = method_getImplementation(originalMethod);
+    const char *types = method_getTypeEncoding(originalMethod);
+
+    Class metaClass = object_getClass(mockedClass);
+    IMP forwarderIMP = [originalMetaClass instanceMethodForwarderForSelector:selector];
+    class_replaceMethod(metaClass, selector, forwarderIMP, types);
+    class_addMethod(metaClass, aliasSelector, originalIMP, types);
+}
+
+
+- (void)forwardInvocationForClassObject:(NSInvocation *)anInvocation
+{
+	// in here "self" is a reference to the real class, not the mock
+	OCClassMockObject *mock = OCMGetAssociatedMockForClass((Class) self, YES);
+    if(mock == nil)
+    {
+        [NSException raise:NSInternalInconsistencyException format:@"No mock for class %@", NSStringFromClass((Class)self)];
+    }
+	if([mock handleInvocation:anInvocation] == NO)
+    {
+        [anInvocation setSelector:OCMAliasForOriginalSelector([anInvocation selector])];
+        [anInvocation invoke];
+    }
+}
+
+- (void)initializeForClassObject
+{
+    // we really just want to have an implementation so that the superclass's is not called
+}
+
+
+#pragma mark  Proxy API
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
+{
+    return [mockedClass instanceMethodSignatureForSelector:aSelector];
+}
+
+- (Class)mockObjectClass
+{
+    return [super class];
+}
+
+- (Class)class
+{
+    return mockedClass;
+}
+
+- (BOOL)respondsToSelector:(SEL)selector
+{
+    return [mockedClass instancesRespondToSelector:selector];
+}
+
+- (BOOL)isKindOfClass:(Class)aClass
+{
+    return [mockedClass isSubclassOfClass:aClass];
+}
+
+- (BOOL)conformsToProtocol:(Protocol *)aProtocol
+{
+    return class_conformsToProtocol(mockedClass, aProtocol);
+}
+
+@end
+
+
+#pragma mark  -
+
+/**
+ taken from:
+ `class-dump -f isNS /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/Frameworks/CoreFoundation.framework`
+ 
+ @interface NSObject (__NSIsKinds)
+ - (_Bool)isNSValue__;
+ - (_Bool)isNSTimeZone__;
+ - (_Bool)isNSString__;
+ - (_Bool)isNSSet__;
+ - (_Bool)isNSOrderedSet__;
+ - (_Bool)isNSNumber__;
+ - (_Bool)isNSDictionary__;
+ - (_Bool)isNSDate__;
+ - (_Bool)isNSData__;
+ - (_Bool)isNSArray__;
+ */
+
+@implementation OCClassMockObject(NSIsKindsImplementation)
+
+- (BOOL)isNSValue__
+{
+    return [mockedClass isKindOfClass:[NSValue class]];
+}
+
+- (BOOL)isNSTimeZone__
+{
+    return [mockedClass isKindOfClass:[NSTimeZone class]];
+}
+
+- (BOOL)isNSSet__
+{
+    return [mockedClass isKindOfClass:[NSSet class]];
+}
+
+- (BOOL)isNSOrderedSet__
+{
+    return [mockedClass isKindOfClass:[NSOrderedSet class]];
+}
+
+- (BOOL)isNSNumber__
+{
+    return [mockedClass isKindOfClass:[NSNumber class]];
+}
+
+- (BOOL)isNSDate__
+{
+    return [mockedClass isKindOfClass:[NSDate class]];
+}
+
+- (BOOL)isNSString__
+{
+    return [mockedClass isKindOfClass:[NSString class]];
+}
+
+- (BOOL)isNSDictionary__
+{
+    return [mockedClass isKindOfClass:[NSDictionary class]];
+}
+
+- (BOOL)isNSData__
+{
+    return [mockedClass isKindOfClass:[NSData class]];
+}
+
+- (BOOL)isNSArray__
+{
+    return [mockedClass isKindOfClass:[NSArray class]];
+}
+
+@end
diff --git a/Source/OCMock/OCMArg.h b/Source/OCMock/OCMArg.h
new file mode 100644
index 0000000..d53437c
--- /dev/null
+++ b/Source/OCMock/OCMArg.h
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMArg : NSObject 
+
+// constraining arguments
+
++ (id)any;
++ (SEL)anySelector;
++ (void *)anyPointer;
++ (id __autoreleasing *)anyObjectRef;
++ (id)isNil;
++ (id)isNotNil;
++ (id)isEqual:(id)value;
++ (id)isNotEqual:(id)value;
++ (id)isKindOfClass:(Class)cls;
++ (id)checkWithSelector:(SEL)selector onObject:(id)anObject;
++ (id)checkWithBlock:(BOOL (^)(id obj))block;
+
+// manipulating arguments
+
++ (id *)setTo:(id)value;
++ (void *)setToValue:(NSValue *)value;
+
+// internal use only
+
++ (id)resolveSpecialValues:(NSValue *)value;
+
+@end
+
+#define OCMOCK_ANY [OCMArg any]
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+  #define OCMOCK_VALUE(variable) \
+    ({ __typeof__(variable) __v = (variable); [NSValue value:&__v withObjCType:@encode(__typeof__(__v))]; })
+#else
+  #define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(__typeof__(variable))]
+#endif
diff --git a/Source/OCMock/OCMArg.m b/Source/OCMock/OCMArg.m
new file mode 100644
index 0000000..06ec394
--- /dev/null
+++ b/Source/OCMock/OCMArg.m
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import <OCMock/OCMArg.h>
+#import <OCMock/OCMConstraint.h>
+#import "OCMPassByRefSetter.h"
+
+@implementation OCMArg
+
++ (id)any
+{
+	return [OCMAnyConstraint constraint];
+}
+
++ (void *)anyPointer
+{
+	return (void *)0x01234567;
+}
+
++ (id __autoreleasing *)anyObjectRef
+{
+    return (id *)0x01234567;
+}
+
++ (SEL)anySelector
+{
+    return NSSelectorFromString(@"aSelectorThatMatchesAnySelector");
+}
+
++ (id)isNil
+{
+	return [OCMIsNilConstraint constraint];
+}
+
++ (id)isNotNil
+{
+	return [OCMIsNotNilConstraint constraint];
+}
+
++ (id)isEqual:(id)value
+{
+    return value;
+}
+
++ (id)isNotEqual:(id)value
+{
+	OCMIsNotEqualConstraint *constraint = [OCMIsNotEqualConstraint constraint];
+	constraint->testValue = value;
+	return constraint;
+}
+
++ (id)isKindOfClass:(Class)cls
+{
+	return [[[OCMBlockConstraint alloc] initWithConstraintBlock:^BOOL(id obj) {
+        return [obj isKindOfClass:cls];
+    }] autorelease];
+}
+
++ (id)checkWithSelector:(SEL)selector onObject:(id)anObject
+{
+	return [OCMConstraint constraintWithSelector:selector onObject:anObject];
+}
+
++ (id)checkWithBlock:(BOOL (^)(id))block
+{
+	return [[[OCMBlockConstraint alloc] initWithConstraintBlock:block] autorelease];
+}
+
++ (id *)setTo:(id)value
+{
+	return (id *)[[[OCMPassByRefSetter alloc] initWithValue:value] autorelease];
+}
+
++ (void *)setToValue:(NSValue *)value
+{
+	return (id *)[[[OCMPassByRefSetter alloc] initWithValue:value] autorelease];
+}
+
++ (id)resolveSpecialValues:(NSValue *)value
+{
+	const char *type = [value objCType];
+	if(type[0] == '^')
+	{
+		void *pointer = [value pointerValue];
+		if(pointer == (void *)0x01234567)
+			return [OCMArg any];
+		if((pointer != NULL) && (object_getClass((id)pointer) == [OCMPassByRefSetter class]))
+			return (id)pointer;
+	}
+    else if(type[0] == ':')
+    {
+        SEL selector;
+        [value getValue:&selector];
+        if(selector == NSSelectorFromString(@"aSelectorThatMatchesAnySelector"))
+            return [OCMArg any];
+    }
+	return value;
+}
+
+
+@end
diff --git a/Source/OCMock/OCMBlockCaller.h b/Source/OCMock/OCMBlockCaller.h
new file mode 100644
index 0000000..c0fe571
--- /dev/null
+++ b/Source/OCMock/OCMBlockCaller.h
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2010-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+
+@interface OCMBlockCaller : NSObject 
+{
+	void (^block)(NSInvocation *);
+}
+
+- (id)initWithCallBlock:(void (^)(NSInvocation *))theBlock;
+
+- (void)handleInvocation:(NSInvocation *)anInvocation;
+
+@end
+
diff --git a/Source/OCMock/OCMBlockCaller.m b/Source/OCMock/OCMBlockCaller.m
new file mode 100644
index 0000000..5b1aec6
--- /dev/null
+++ b/Source/OCMock/OCMBlockCaller.m
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2010-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMBlockCaller.h"
+
+
+@implementation OCMBlockCaller
+
+-(id)initWithCallBlock:(void (^)(NSInvocation *))theBlock 
+{
+	self = [super init];
+	block = [theBlock copy];
+	return self;
+}
+
+-(void)dealloc 
+{
+	[block release];
+	[super dealloc];
+}
+
+- (void)handleInvocation:(NSInvocation *)anInvocation
+{
+    if (block != nil)
+    {
+        block(anInvocation);
+    }
+}
+
+@end
diff --git a/Source/OCMock/OCMBoxedReturnValueProvider.h b/Source/OCMock/OCMBoxedReturnValueProvider.h
new file mode 100644
index 0000000..467f691
--- /dev/null
+++ b/Source/OCMock/OCMBoxedReturnValueProvider.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMReturnValueProvider.h"
+
+@interface OCMBoxedReturnValueProvider : OCMReturnValueProvider 
+{
+}
+
+@end
diff --git a/Source/OCMock/OCMBoxedReturnValueProvider.m b/Source/OCMock/OCMBoxedReturnValueProvider.m
new file mode 100644
index 0000000..03ed54f
--- /dev/null
+++ b/Source/OCMock/OCMBoxedReturnValueProvider.m
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMBoxedReturnValueProvider.h"
+#import "OCMFunctions.h"
+#import "NSValue+OCMAdditions.h"
+
+@implementation OCMBoxedReturnValueProvider
+
+- (void)handleInvocation:(NSInvocation *)anInvocation
+{
+	const char *returnType = [[anInvocation methodSignature] methodReturnType];
+    NSUInteger returnTypeSize = [[anInvocation methodSignature] methodReturnLength];
+    char valueBuffer[returnTypeSize];
+    NSValue *returnValueAsNSValue = (NSValue *)returnValue;
+
+    if([self isMethodReturnType:returnType compatibleWithValueType:[returnValueAsNSValue objCType]])
+    {
+        [returnValueAsNSValue getValue:valueBuffer];
+        [anInvocation setReturnValue:valueBuffer];
+    }
+    else if([returnValueAsNSValue getBytes:valueBuffer objCType:returnType])
+    {
+        [anInvocation setReturnValue:valueBuffer];
+    }
+    else
+    {
+        [NSException raise:NSInvalidArgumentException
+                    format:@"Return value cannot be used for method; method signature declares '%s' but value is '%s'.", returnType, [returnValueAsNSValue objCType]];
+    }
+}
+
+
+- (BOOL)isMethodReturnType:(const char *)returnType compatibleWithValueType:(const char *)valueType
+{
+    /* Same types are obviously compatible */
+    if(strcmp(returnType, valueType) == 0)
+        return YES;
+
+    /* Allow void* for methods that return id, mainly to be able to handle nil */
+    if(strcmp(returnType, @encode(id)) == 0 && strcmp(valueType, @encode(void *)) == 0)
+        return YES;
+
+    return OCMEqualTypesAllowingOpaqueStructs(returnType, valueType);
+}
+
+
+@end
diff --git a/Source/OCMock/OCMConstraint.h b/Source/OCMock/OCMConstraint.h
new file mode 100644
index 0000000..777966a
--- /dev/null
+++ b/Source/OCMock/OCMConstraint.h
@@ -0,0 +1,71 @@
+/*
+ *  Copyright (c) 2007-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+
+@interface OCMConstraint : NSObject 
+
++ (instancetype)constraint;
+- (BOOL)evaluate:(id)value;
+
+// if you are looking for any, isNil, etc, they have moved to OCMArg
+
+// try to use [OCMArg checkWith...] instead of the constraintWith... methods below
+
++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject;
++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue;
+
+
+@end
+
+@interface OCMAnyConstraint : OCMConstraint
+@end
+
+@interface OCMIsNilConstraint : OCMConstraint
+@end
+
+@interface OCMIsNotNilConstraint : OCMConstraint
+@end
+
+@interface OCMIsNotEqualConstraint : OCMConstraint
+{
+	@public
+	id testValue;
+}
+
+@end
+
+@interface OCMInvocationConstraint : OCMConstraint
+{
+	@public
+	NSInvocation *invocation;
+}
+
+@end
+
+@interface OCMBlockConstraint : OCMConstraint
+{
+	BOOL (^block)(id);
+}
+
+- (instancetype)initWithConstraintBlock:(BOOL (^)(id))block;
+
+@end
+
+
+#define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self]
+#define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)]
diff --git a/Source/OCMock/OCMConstraint.m b/Source/OCMock/OCMConstraint.m
new file mode 100644
index 0000000..5fbe949
--- /dev/null
+++ b/Source/OCMock/OCMConstraint.m
@@ -0,0 +1,153 @@
+/*
+ *  Copyright (c) 2007-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <OCMock/OCMConstraint.h>
+
+
+@implementation OCMConstraint
+
++ (instancetype)constraint
+{
+	return [[[self alloc] init] autorelease];
+}
+
+- (BOOL)evaluate:(id)value
+{
+	return NO;
+}
+
+- (id)copyWithZone:(struct _NSZone *)zone
+{
+    return [self retain];
+}
+
++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject
+{
+	OCMInvocationConstraint *constraint = [OCMInvocationConstraint constraint];
+	NSMethodSignature *signature = [anObject methodSignatureForSelector:aSelector]; 
+	if(signature == nil)
+		[NSException raise:NSInvalidArgumentException format:@"Unkown selector %@ used in constraint.", NSStringFromSelector(aSelector)];
+	NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+	[invocation setTarget:anObject];
+	[invocation setSelector:aSelector];
+	constraint->invocation = invocation;
+	return constraint;
+}
+
++ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue
+{
+	OCMInvocationConstraint *constraint = [self constraintWithSelector:aSelector onObject:anObject];
+	if([[constraint->invocation methodSignature] numberOfArguments] < 4)
+		[NSException raise:NSInvalidArgumentException format:@"Constraint with value requires selector with two arguments."];
+	[constraint->invocation setArgument:&aValue atIndex:3];
+	return constraint;
+}
+
+
+@end
+
+
+
+#pragma mark  -
+
+@implementation OCMAnyConstraint
+
+- (BOOL)evaluate:(id)value
+{
+	return YES;
+}
+
+@end
+
+
+
+#pragma mark  -
+
+@implementation OCMIsNilConstraint
+
+- (BOOL)evaluate:(id)value
+{
+	return value == nil;
+}
+
+@end
+
+
+
+#pragma mark  -
+
+@implementation OCMIsNotNilConstraint
+
+- (BOOL)evaluate:(id)value
+{
+	return value != nil;
+}
+
+@end
+
+
+
+#pragma mark  -
+
+@implementation OCMIsNotEqualConstraint
+
+- (BOOL)evaluate:(id)value
+{
+	return ![value isEqual:testValue];
+}
+
+@end
+
+
+
+#pragma mark  -
+
+@implementation OCMInvocationConstraint
+
+- (BOOL)evaluate:(id)value
+{
+	[invocation setArgument:&value atIndex:2]; // should test if constraint takes arg
+	[invocation invoke];
+	BOOL returnValue;
+	[invocation getReturnValue:&returnValue];
+	return returnValue;
+}
+
+@end
+
+#pragma mark  -
+
+@implementation OCMBlockConstraint
+
+- (instancetype)initWithConstraintBlock:(BOOL (^)(id))aBlock
+{
+	self = [super init];
+	block = [aBlock copy];
+	return self;
+}
+
+- (void)dealloc {
+    [block release];
+    [super dealloc];
+}
+
+- (BOOL)evaluate:(id)value 
+{
+	return block(value);
+}
+
+
+@end
diff --git a/Source/OCMock/OCMExceptionReturnValueProvider.h b/Source/OCMock/OCMExceptionReturnValueProvider.h
new file mode 100644
index 0000000..8d2d2d6
--- /dev/null
+++ b/Source/OCMock/OCMExceptionReturnValueProvider.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMReturnValueProvider.h"
+
+@interface OCMExceptionReturnValueProvider : OCMReturnValueProvider 
+{
+}
+
+@end
diff --git a/Source/OCMock/OCMExceptionReturnValueProvider.m b/Source/OCMock/OCMExceptionReturnValueProvider.m
new file mode 100644
index 0000000..bb1f685
--- /dev/null
+++ b/Source/OCMock/OCMExceptionReturnValueProvider.m
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMExceptionReturnValueProvider.h"
+
+
+@implementation OCMExceptionReturnValueProvider
+
+- (void)handleInvocation:(NSInvocation *)anInvocation
+{
+	@throw returnValue;
+}
+
+@end
diff --git a/Source/OCMock/OCMExpectationRecorder.h b/Source/OCMock/OCMExpectationRecorder.h
new file mode 100644
index 0000000..fae5c4c
--- /dev/null
+++ b/Source/OCMock/OCMExpectationRecorder.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2004-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <OCMock/OCMock.h>
+
+@interface OCMExpectationRecorder : OCMStubRecorder
+
+- (id)never;
+
+@end
diff --git a/Source/OCMock/OCMExpectationRecorder.m b/Source/OCMock/OCMExpectationRecorder.m
new file mode 100644
index 0000000..c530ddf
--- /dev/null
+++ b/Source/OCMock/OCMExpectationRecorder.m
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2004-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMExpectationRecorder.h"
+#import "OCMInvocationExpectation.h"
+
+@implementation OCMExpectationRecorder
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (id)init
+{
+    self = [super init];
+    [invocationMatcher release];
+    invocationMatcher = [[OCMInvocationExpectation alloc] init];
+    return self;
+}
+
+- (OCMInvocationExpectation *)expectation
+{
+    return (OCMInvocationExpectation *)invocationMatcher;
+}
+
+
+#pragma mark Modifying the expectation
+
+- (id)never
+{
+    [[self expectation] setMatchAndReject:YES];
+    return self;
+}
+
+
+#pragma mark Finishing recording
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation
+{
+    [super forwardInvocation:anInvocation];
+    [mockObject addExpectation:[self expectation]];
+}
+
+
+@end
diff --git a/Source/OCMock/OCMFunctions.h b/Source/OCMock/OCMFunctions.h
new file mode 100644
index 0000000..5d1d31c
--- /dev/null
+++ b/Source/OCMock/OCMFunctions.h
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class OCMLocation;
+@class OCClassMockObject;
+@class OCPartialMockObject;
+
+
+BOOL OCMIsObjectType(const char *objCType);
+const char *OCMTypeWithoutQualifiers(const char *objCType);
+BOOL OCMEqualTypesAllowingOpaqueStructs(const char *type1, const char *type2);
+
+Class OCMCreateSubclass(Class class, void *ref);
+
+void OCMSetIsa(id object, Class class);
+Class OCMGetIsa(id object);
+
+BOOL OCMIsAliasSelector(SEL selector);
+SEL OCMAliasForOriginalSelector(SEL selector);
+SEL OCMOriginalSelectorForAlias(SEL selector);
+
+void OCMSetAssociatedMockForClass(OCClassMockObject *mock, Class aClass);
+OCClassMockObject *OCMGetAssociatedMockForClass(Class aClass, BOOL includeSuperclasses);
+
+void OCMSetAssociatedMockForObject(OCClassMockObject *mock, id anObject);
+OCPartialMockObject *OCMGetAssociatedMockForObject(id anObject);
+
+void OCMReportFailure(OCMLocation *loc, NSString *description);
diff --git a/Source/OCMock/OCMFunctions.m b/Source/OCMock/OCMFunctions.m
new file mode 100644
index 0000000..b7b6fb4
--- /dev/null
+++ b/Source/OCMock/OCMFunctions.m
@@ -0,0 +1,292 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import "OCMFunctions.h"
+#import "OCMLocation.h"
+#import "OCClassMockObject.h"
+#import "OCPartialMockObject.h"
+
+
+#pragma mark  Known private API
+
+@interface NSException(OCMKnownExceptionMethods)
++ (NSException *)failureInFile:(NSString *)file atLine:(int)line withDescription:(NSString *)formatString, ...;
+@end
+
+@interface NSObject(OCMKnownTestCaseMethods)
+- (void)recordFailureWithDescription:(NSString *)description inFile:(NSString *)file atLine:(NSUInteger)line expected:(BOOL)expected;
+- (void)failWithException:(NSException *)exception;
+@end
+
+
+#pragma mark  Functions related to ObjC type system
+
+BOOL OCMIsObjectType(const char *objCType)
+{
+    objCType = OCMTypeWithoutQualifiers(objCType);
+
+    if(strcmp(objCType, @encode(id)) == 0 || strcmp(objCType, @encode(Class)) == 0)
+        return YES;
+
+    // if the returnType is a typedef to an object, it has the form ^{OriginClass=#}
+    NSString *regexString = @"^\\^\\{(.*)=#.*\\}";
+    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:NULL];
+    NSString *type = [NSString stringWithCString:objCType encoding:NSASCIIStringEncoding];
+    if([regex numberOfMatchesInString:type options:0 range:NSMakeRange(0, type.length)] > 0)
+        return YES;
+
+    // if the return type is a block we treat it like an object
+    // TODO: if the runtime were to encode the block's argument and/or return types, this test would not be sufficient
+    if(strcmp(objCType, @encode(void(^)())) == 0)
+        return YES;
+
+    return NO;
+}
+
+
+const char *OCMTypeWithoutQualifiers(const char *objCType)
+{
+    while(strchr("rnNoORV", objCType[0]) != NULL)
+        objCType += 1;
+    return objCType;
+}
+
+
+/*
+ * Sometimes an external type is an opaque struct (which will have an @encode of "{structName}"
+ * or "{structName=}") but the actual method return type, or property type, will know the contents
+ * of the struct (so will have an objcType of say "{structName=iiSS}".  This function will determine
+ * those are equal provided they have the same structure name, otherwise everything else will be
+ * compared textually.  This can happen particularly for pointers to such structures, which still
+ * encode what is being pointed to.
+ *
+ * For some types some runtime functions throw exceptions, which is why we wrap this in an
+ * exception handler just below.
+ */
+static BOOL OCMEqualTypesAllowingOpaqueStructsInternal(const char *type1, const char *type2)
+{
+    type1 = OCMTypeWithoutQualifiers(type1);
+    type2 = OCMTypeWithoutQualifiers(type2);
+
+    switch (type1[0])
+    {
+        case '{':
+        case '(':
+        {
+            if (type2[0] != type1[0])
+                return NO;
+            char endChar = type1[0] == '{'? '}' : ')';
+
+            const char *type1End = strchr(type1, endChar);
+            const char *type2End = strchr(type2, endChar);
+            const char *type1Equals = strchr(type1, '=');
+            const char *type2Equals = strchr(type2, '=');
+
+            /* Opaque types either don't have an equals sign (just the name and the end brace), or
+             * empty content after the equals sign.
+             * We want that to compare the same as a type of the same name but with the content.
+             */
+            BOOL type1Opaque = (type1Equals == NULL || (type1End < type1Equals) || type1Equals[1] == endChar);
+            BOOL type2Opaque = (type2Equals == NULL || (type2End < type2Equals) || type2Equals[1] == endChar);
+            const char *type1NameEnd = (type1Equals == NULL || (type1End < type1Equals)) ? type1End : type1Equals;
+            const char *type2NameEnd = (type1Equals == NULL || (type2End < type2Equals)) ? type2End : type2Equals;
+            intptr_t type1NameLen = type1NameEnd - type1;
+            intptr_t type2NameLen = type2NameEnd - type2;
+
+            /* If the names are not equal, return NO */
+            if (type1NameLen != type2NameLen || strncmp(type1, type2, type1NameLen))
+                return NO;
+
+            /* If the same name, and at least one is opaque, that is close enough. */
+            if (type1Opaque || type2Opaque)
+                return YES;
+
+            /* Otherwise, compare all the elements.  Use NSGetSizeAndAlignment to walk through the struct elements. */
+            type1 = type1Equals + 1;
+            type2 = type2Equals + 1;
+            while (type1[0] != endChar && type1[0] != '\0')
+            {
+                if (!OCMEqualTypesAllowingOpaqueStructs(type1, type2))
+                    return NO;
+                type1 = NSGetSizeAndAlignment(type1, NULL, NULL);
+                type2 = NSGetSizeAndAlignment(type2, NULL, NULL);
+            }
+            return YES;
+        }
+        case '^':
+            /* for a pointer, make sure the other is a pointer, then recursively compare the rest */
+            if (type2[0] != type1[0])
+                return NO;
+            return OCMEqualTypesAllowingOpaqueStructs(type1 + 1, type2 + 1);
+
+        case '\0':
+            return type2[0] == '\0';
+
+        default:
+        {
+            // Move the type pointers past the current types, then compare that region
+            const char *afterType1 =  NSGetSizeAndAlignment(type1, NULL, NULL);
+            const char *afterType2 =  NSGetSizeAndAlignment(type2, NULL, NULL);
+            intptr_t type1Len = afterType1 - type1;
+            intptr_t type2Len = afterType2 - type2;
+
+            return (type1Len == type2Len && (strncmp(type1, type2, type1Len) == 0));
+        }
+    }
+}
+
+BOOL OCMEqualTypesAllowingOpaqueStructs(const char *type1, const char *type2)
+{
+    @try
+    {
+        return OCMEqualTypesAllowingOpaqueStructsInternal(type1, type2);
+    }
+    @catch (NSException *e)
+    {
+        /* Probably a bitfield or something that NSGetSizeAndAlignment chokes on, oh well */
+        return NO;
+    }
+}
+
+
+#pragma mark  Creating classes
+
+Class OCMCreateSubclass(Class class, void *ref)
+{
+    const char *className = [[NSString stringWithFormat:@"%@-%p-%u", NSStringFromClass(class), ref, arc4random()] UTF8String];
+    Class subclass = objc_allocateClassPair(class, className, 0);
+    objc_registerClassPair(subclass);
+    return subclass;
+}
+
+
+#pragma mark  Directly manipulating the isa pointer (look away)
+
+void OCMSetIsa(id object, Class class)
+{
+    *((Class *)object) = class;
+}
+
+Class OCMGetIsa(id object)
+{
+    return *((Class *)object);
+}
+
+
+#pragma mark  Alias for renaming real methods
+
+NSString *OCMRealMethodAliasPrefix = @"ocmock_replaced_";
+const char *OCMRealMethodAliasPrefixCString = "ocmock_replaced_";
+
+BOOL OCMIsAliasSelector(SEL selector)
+{
+    return [NSStringFromSelector(selector) hasPrefix:OCMRealMethodAliasPrefix];
+}
+
+SEL OCMAliasForOriginalSelector(SEL selector)
+{
+    char aliasName[2048];
+    const char *originalName = sel_getName(selector);
+    strlcpy(aliasName, OCMRealMethodAliasPrefixCString, sizeof(aliasName));
+    strlcat(aliasName, originalName, sizeof(aliasName));
+    return sel_registerName(aliasName);
+}
+
+SEL OCMOriginalSelectorForAlias(SEL selector)
+{
+    if(!OCMIsAliasSelector(selector))
+        [NSException raise:NSInvalidArgumentException format:@"Not an alias selector; found %@", NSStringFromSelector(selector)];
+    NSString *string = NSStringFromSelector(selector);
+    return NSSelectorFromString([string substringFromIndex:[OCMRealMethodAliasPrefix length]]);
+}
+
+
+#pragma mark  Wrappers around associative references
+
+NSString *OCMClassMethodMockObjectKey = @"OCMClassMethodMockObjectKey";
+
+void OCMSetAssociatedMockForClass(OCClassMockObject *mock, Class aClass)
+{
+    if((mock != nil) && (objc_getAssociatedObject(aClass, OCMClassMethodMockObjectKey) != nil))
+        [NSException raise:NSInternalInconsistencyException format:@"Another mock is already associated with class %@", NSStringFromClass(aClass)];
+    objc_setAssociatedObject(aClass, OCMClassMethodMockObjectKey, mock, OBJC_ASSOCIATION_ASSIGN);
+}
+
+OCClassMockObject *OCMGetAssociatedMockForClass(Class aClass, BOOL includeSuperclasses)
+{
+    OCClassMockObject *mock = nil;
+    do
+    {
+        mock = objc_getAssociatedObject(aClass, OCMClassMethodMockObjectKey);
+        aClass = class_getSuperclass(aClass);
+    }
+    while((mock == nil) && (aClass != nil) && includeSuperclasses);
+    return mock;
+}
+
+NSString *OCMPartialMockObjectKey = @"OCMPartialMockObjectKey";
+
+void OCMSetAssociatedMockForObject(OCClassMockObject *mock, id anObject)
+{
+    if((mock != nil) && (objc_getAssociatedObject(anObject, OCMPartialMockObjectKey) != nil))
+        [NSException raise:NSInternalInconsistencyException format:@"Another mock is already associated with object %@", anObject];
+    objc_setAssociatedObject(anObject, OCMPartialMockObjectKey, mock, OBJC_ASSOCIATION_ASSIGN);
+}
+
+OCPartialMockObject *OCMGetAssociatedMockForObject(id anObject)
+{
+    return objc_getAssociatedObject(anObject, OCMPartialMockObjectKey);
+}
+
+
+#pragma mark  Functions related to IDE error reporting
+
+void OCMReportFailure(OCMLocation *loc, NSString *description)
+{
+    id testCase = [loc testCase];
+    if((testCase != nil) && [testCase respondsToSelector:@selector(recordFailureWithDescription:inFile:atLine:expected:)])
+    {
+        [testCase recordFailureWithDescription:description inFile:[loc file] atLine:[loc line] expected:NO];
+    }
+    else if((testCase != nil) && [testCase respondsToSelector:@selector(failWithException:)])
+    {
+        NSException *exception = nil;
+        if([NSException instancesRespondToSelector:@selector(failureInFile:atLine:withDescription:)])
+        {
+            exception = [NSException failureInFile:[loc file] atLine:(int)[loc line] withDescription:description];
+        }
+        else
+        {
+            NSString *reason = [NSString stringWithFormat:@"%@:%lu %@", [loc file], (unsigned long)[loc line], description];
+            exception = [NSException exceptionWithName:@"OCMockTestFailure" reason:reason userInfo:nil];
+        }
+        [testCase failWithException:exception];
+    }
+    else if(loc != nil)
+    {
+        NSLog(@"%@:%lu %@", [loc file], (unsigned long)[loc line], description);
+        NSString *reason = [NSString stringWithFormat:@"%@:%lu %@", [loc file], (unsigned long)[loc line], description];
+        [[NSException exceptionWithName:@"OCMockTestFailure" reason:reason userInfo:nil] raise];
+
+    }
+    else
+    {
+        NSLog(@"%@", description);
+        [[NSException exceptionWithName:@"OCMockTestFailure" reason:description userInfo:nil] raise];
+    }
+
+}
diff --git a/Source/OCMock/OCMIndirectReturnValueProvider.h b/Source/OCMock/OCMIndirectReturnValueProvider.h
new file mode 100644
index 0000000..ce35a86
--- /dev/null
+++ b/Source/OCMock/OCMIndirectReturnValueProvider.h
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMIndirectReturnValueProvider : NSObject 
+{
+	id	provider;
+	SEL	selector;
+}
+
+- (id)initWithProvider:(id)aProvider andSelector:(SEL)aSelector;
+
+- (void)handleInvocation:(NSInvocation *)anInvocation;
+
+@end
diff --git a/Source/OCMock/OCMIndirectReturnValueProvider.m b/Source/OCMock/OCMIndirectReturnValueProvider.m
new file mode 100644
index 0000000..28b7c59
--- /dev/null
+++ b/Source/OCMock/OCMIndirectReturnValueProvider.m
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "NSMethodSignature+OCMAdditions.h"
+#import "OCMIndirectReturnValueProvider.h"
+
+
+@implementation OCMIndirectReturnValueProvider
+
+- (id)initWithProvider:(id)aProvider andSelector:(SEL)aSelector
+{
+	self = [super init];
+	provider = [aProvider retain];
+	selector = aSelector;
+	return self;
+}
+
+- (void)dealloc
+{
+	[provider release];
+	[super dealloc];
+}
+
+- (void)handleInvocation:(NSInvocation *)anInvocation
+{
+	[anInvocation setTarget:provider];
+	[anInvocation setSelector:selector];
+	[anInvocation invoke];
+}
+
+@end
diff --git a/Source/OCMock/OCMInvocationExpectation.h b/Source/OCMock/OCMInvocationExpectation.h
new file mode 100644
index 0000000..8fcb85a
--- /dev/null
+++ b/Source/OCMock/OCMInvocationExpectation.h
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMInvocationStub.h"
+
+@interface OCMInvocationExpectation : OCMInvocationStub
+{
+    BOOL matchAndReject;
+    BOOL isSatisfied;
+}
+
+- (void)setMatchAndReject:(BOOL)flag;
+
+- (BOOL)isSatisfied;
+
+@end
\ No newline at end of file
diff --git a/Source/OCMock/OCMInvocationExpectation.m b/Source/OCMock/OCMInvocationExpectation.m
new file mode 100644
index 0000000..856b4f1
--- /dev/null
+++ b/Source/OCMock/OCMInvocationExpectation.m
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMInvocationExpectation.h"
+#import "NSInvocation+OCMAdditions.h"
+
+
+@implementation OCMInvocationExpectation
+
+- (void)setMatchAndReject:(BOOL)flag
+{
+    matchAndReject = flag;
+    if(matchAndReject)
+        isSatisfied = YES;
+}
+
+- (BOOL)isSatisfied
+{
+    return isSatisfied;
+}
+
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation
+{
+    BOOL result = [super handleInvocation:anInvocation];
+    if(result)
+    {
+        isSatisfied = !matchAndReject;
+        if(matchAndReject)
+        {
+            [NSException raise:NSInternalInconsistencyException format:@"%@: explicitly disallowed method invoked: %@",
+                    [self description], [anInvocation invocationDescription]];
+        }
+    }
+    return result;
+}
+
+@end
\ No newline at end of file
diff --git a/Source/OCMock/OCMInvocationMatcher.h b/Source/OCMock/OCMInvocationMatcher.h
new file mode 100644
index 0000000..ca3ccb2
--- /dev/null
+++ b/Source/OCMock/OCMInvocationMatcher.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMInvocationMatcher : NSObject
+{
+    NSInvocation *recordedInvocation;
+    BOOL         recordedAsClassMethod;
+    BOOL         ignoreNonObjectArgs;
+}
+
+- (void)setInvocation:(NSInvocation *)anInvocation;
+- (NSInvocation *)recordedInvocation;
+
+- (void)setRecordedAsClassMethod:(BOOL)flag;
+- (BOOL)recordedAsClassMethod;
+
+- (void)setIgnoreNonObjectArgs:(BOOL)flag;
+
+- (BOOL)matchesSelector:(SEL)aSelector;
+- (BOOL)matchesInvocation:(NSInvocation *)anInvocation;
+
+@end
diff --git a/Source/OCMock/OCMInvocationMatcher.m b/Source/OCMock/OCMInvocationMatcher.m
new file mode 100644
index 0000000..d9e18c0
--- /dev/null
+++ b/Source/OCMock/OCMInvocationMatcher.m
@@ -0,0 +1,144 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import <OCMock/OCMArg.h>
+#import <OCMock/OCMConstraint.h>
+#import "OCMPassByRefSetter.h"
+#import "NSInvocation+OCMAdditions.h"
+#import "OCMInvocationMatcher.h"
+#import "OCClassMockObject.h"
+#import "OCMFunctions.h"
+
+
+@interface NSObject(HCMatcherDummy)
+- (BOOL)matches:(id)item;
+@end
+
+
+@implementation OCMInvocationMatcher
+
+- (void)setInvocation:(NSInvocation *)anInvocation
+{
+    [recordedInvocation release];
+    // When the method has a char* argument we do not retain the arguments. This makes it possible
+    // to match char* args literally and with anyPointer. Not retaining the argument means that
+    // in these cases tests that use their own autorelease pools may fail unexpectedly.
+    if(![anInvocation hasCharPointerArgument])
+        [anInvocation retainArguments];
+    recordedInvocation = [anInvocation retain];
+}
+
+- (void)setRecordedAsClassMethod:(BOOL)flag
+{
+    recordedAsClassMethod = flag;
+}
+
+- (BOOL)recordedAsClassMethod
+{
+    return recordedAsClassMethod;
+}
+
+- (void)setIgnoreNonObjectArgs:(BOOL)flag
+{
+    ignoreNonObjectArgs = flag;
+}
+
+- (NSString *)description
+{
+    return [recordedInvocation invocationDescription];
+}
+
+- (NSInvocation *)recordedInvocation
+{
+    return recordedInvocation;
+}
+
+- (BOOL)matchesSelector:(SEL)sel
+{
+    if(sel == [recordedInvocation selector])
+        return YES;
+    if(OCMIsAliasSelector(sel) &&
+       OCMOriginalSelectorForAlias(sel) == [recordedInvocation selector])
+        return YES;
+
+    return NO;
+}
+
+- (BOOL)matchesInvocation:(NSInvocation *)anInvocation
+{
+    id target = [anInvocation target];
+    BOOL isClassMethodInvocation = (target != nil) && (target == [target class]);
+    if(isClassMethodInvocation != recordedAsClassMethod)
+        return NO;
+
+    if(![self matchesSelector:[anInvocation selector]])
+        return NO;
+
+    NSMethodSignature *signature = [recordedInvocation methodSignature];
+    int n = (int)[signature numberOfArguments];
+    for(int i = 2; i < n; i++)
+    {
+        if(ignoreNonObjectArgs && strcmp([signature getArgumentTypeAtIndex:i], @encode(id)))
+        {
+            continue;
+        }
+
+        id recordedArg = [recordedInvocation getArgumentAtIndexAsObject:i];
+        id passedArg = [anInvocation getArgumentAtIndexAsObject:i];
+
+        if([recordedArg isProxy])
+        {
+            if(![recordedArg isEqual:passedArg])
+                return NO;
+            continue;
+        }
+
+        if([recordedArg isKindOfClass:[NSValue class]])
+            recordedArg = [OCMArg resolveSpecialValues:recordedArg];
+
+        if([recordedArg isKindOfClass:[OCMConstraint class]])
+        {
+            if([recordedArg evaluate:passedArg] == NO)
+                return NO;
+        }
+        else if([recordedArg isKindOfClass:[OCMPassByRefSetter class]])
+        {
+            id valueToSet = [(OCMPassByRefSetter *)recordedArg value];
+            // side effect but easier to do here than in handleInvocation
+            if(![valueToSet isKindOfClass:[NSValue class]])
+                *(id *)[passedArg pointerValue] = valueToSet;
+            else
+                [(NSValue *)valueToSet getValue:[passedArg pointerValue]];
+        }
+        else if([recordedArg conformsToProtocol:objc_getProtocol("HCMatcher")])
+        {
+            if([recordedArg matches:passedArg] == NO)
+                return NO;
+        }
+        else
+        {
+            if(([recordedArg class] == [NSNumber class]) &&
+                    ([(NSNumber*)recordedArg compare:(NSNumber*)passedArg] != NSOrderedSame))
+                return NO;
+            if(([recordedArg isEqual:passedArg] == NO) &&
+                    !((recordedArg == nil) && (passedArg == nil)))
+                return NO;
+        }
+    }
+    return YES;
+}
+@end
diff --git a/Source/OCMock/OCMInvocationStub.h b/Source/OCMock/OCMInvocationStub.h
new file mode 100644
index 0000000..d598798
--- /dev/null
+++ b/Source/OCMock/OCMInvocationStub.h
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMInvocationMatcher.h"
+
+@interface OCMInvocationStub : OCMInvocationMatcher
+{
+    NSMutableArray *invocationActions;
+}
+
+- (void)addInvocationAction:(id)anAction;
+- (NSArray *)invocationActions;
+
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation;
+
+@end
diff --git a/Source/OCMock/OCMInvocationStub.m b/Source/OCMock/OCMInvocationStub.m
new file mode 100644
index 0000000..40a0fe9
--- /dev/null
+++ b/Source/OCMock/OCMInvocationStub.m
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMInvocationStub.h"
+
+@implementation OCMInvocationStub
+
+- (id)init
+{
+    self = [super init];
+    invocationActions = [[NSMutableArray alloc] init];
+    return self;
+}
+
+- (void)dealloc
+{
+    [invocationActions release];
+    [super dealloc];
+}
+
+
+- (void)addInvocationAction:(id)anAction
+{
+    [invocationActions addObject:anAction];
+}
+
+- (NSArray *)invocationActions
+{
+    return invocationActions;
+}
+
+
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation
+{
+    if(![self matchesInvocation:anInvocation])
+        return NO;
+    [invocationActions makeObjectsPerformSelector:@selector(handleInvocation:) withObject:anInvocation];
+    return YES;
+}
+
+@end
diff --git a/Source/OCMock/OCMLocation.h b/Source/OCMock/OCMLocation.h
new file mode 100644
index 0000000..e510db7
--- /dev/null
+++ b/Source/OCMock/OCMLocation.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMLocation : NSObject
+{
+    id          testCase;
+    NSString    *file;
+    NSUInteger  line;
+}
+
++ (instancetype)locationWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
+
+- (instancetype)initWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
+
+- (id)testCase;
+- (NSString *)file;
+- (NSUInteger)line;
+
+@end
+
+extern OCMLocation *OCMMakeLocation(id testCase, const char *file, int line);
diff --git a/Source/OCMock/OCMLocation.m b/Source/OCMock/OCMLocation.m
new file mode 100644
index 0000000..9a3ae21
--- /dev/null
+++ b/Source/OCMock/OCMLocation.m
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMLocation.h"
+
+@implementation OCMLocation
+
++ (instancetype)locationWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine
+{
+    return [[[OCMLocation alloc] initWithTestCase:aTestCase file:aFile line:aLine] autorelease];
+}
+
+- (instancetype)initWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine
+{
+    self = [super init];
+    testCase = aTestCase;
+    file = [aFile retain];
+    line = aLine;
+    return self;
+}
+
+- (void)dealloc
+{
+    [file release];
+    [super dealloc];
+}
+
+- (id)testCase
+{
+    return testCase;
+}
+
+- (NSString *)file
+{
+    return file;
+}
+
+- (NSUInteger)line
+{
+    return line;
+}
+
+@end
+
+
+OCMLocation *OCMMakeLocation(id testCase, const char *fileCString, int line)
+{
+    return [OCMLocation locationWithTestCase:testCase file:[NSString stringWithUTF8String:fileCString] line:line];
+}
+
diff --git a/Source/OCMock/OCMMacroState.h b/Source/OCMock/OCMMacroState.h
new file mode 100644
index 0000000..4b2d635
--- /dev/null
+++ b/Source/OCMock/OCMMacroState.h
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class OCMLocation;
+@class OCMRecorder;
+@class OCMStubRecorder;
+@class OCMockObject;
+
+
+@interface OCMMacroState : NSObject
+{
+    OCMRecorder *recorder;
+}
+
++ (void)beginStubMacro;
++ (OCMStubRecorder *)endStubMacro;
+
++ (void)beginExpectMacro;
++ (OCMStubRecorder *)endExpectMacro;
+
++ (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation;
++ (void)endVerifyMacro;
+
++ (OCMMacroState *)globalState;
+
+- (OCMRecorder *)recorder;
+
+- (void)switchToClassMethod;
+
+@end
diff --git a/Source/OCMock/OCMMacroState.m b/Source/OCMock/OCMMacroState.m
new file mode 100644
index 0000000..43288bb
--- /dev/null
+++ b/Source/OCMock/OCMMacroState.m
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMMacroState.h"
+#import "OCMStubRecorder.h"
+#import "OCMockObject.h"
+#import "OCMExpectationRecorder.h"
+#import "OCMVerifier.h"
+#import "OCMInvocationMatcher.h"
+
+
+@implementation OCMMacroState
+
+OCMMacroState *globalState;
+
+#pragma mark  Methods to begin/end macros
+
++ (void)beginStubMacro
+{
+    OCMStubRecorder *recorder = [[[OCMStubRecorder alloc] init] autorelease];
+    globalState = [[[OCMMacroState alloc] initWithRecorder:recorder] autorelease];
+}
+
++ (OCMStubRecorder *)endStubMacro
+{
+    OCMStubRecorder *recorder = (OCMStubRecorder *)[globalState recorder];
+    globalState = nil;
+    return recorder;
+}
+
+
++ (void)beginExpectMacro
+{
+    OCMExpectationRecorder *recorder = [[[OCMExpectationRecorder alloc] init] autorelease];
+    globalState = [[[OCMMacroState alloc] initWithRecorder:recorder] autorelease];
+}
+
++ (OCMStubRecorder *)endExpectMacro
+{
+    return [self endStubMacro];
+}
+
+
++ (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation
+{
+    OCMVerifier *recorder = [[[OCMVerifier alloc] init] autorelease];
+    [recorder setLocation:aLocation];
+    globalState = [[[OCMMacroState alloc] initWithRecorder:recorder] autorelease];
+}
+
++ (void)endVerifyMacro
+{
+    globalState = nil;
+}
+
+
+#pragma mark  Accessing global state
+
++ (OCMMacroState *)globalState
+{
+    return globalState;
+}
+
+
+#pragma mark  Init, dealloc, accessors
+
+- (id)initWithRecorder:(OCMRecorder *)aRecorder
+{
+    self = [super init];
+    recorder = [aRecorder retain];
+    return self;
+}
+
+- (void)dealloc
+{
+    [recorder release];
+    if(globalState == self)
+        globalState = nil;
+    [super dealloc];
+}
+
+- (OCMRecorder *)recorder
+{
+    return recorder;
+}
+
+
+#pragma mark  Changing the recorder
+
+- (void)switchToClassMethod
+{
+    [recorder classMethod];
+}
+
+
+@end
diff --git a/Source/OCMock/OCMNotificationPoster.h b/Source/OCMock/OCMNotificationPoster.h
new file mode 100644
index 0000000..1c66550
--- /dev/null
+++ b/Source/OCMock/OCMNotificationPoster.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMNotificationPoster : NSObject 
+{
+	NSNotification *notification;
+}
+
+- (id)initWithNotification:(id)aNotification;
+
+- (void)handleInvocation:(NSInvocation *)anInvocation;
+
+@end
diff --git a/Source/OCMock/OCMNotificationPoster.m b/Source/OCMock/OCMNotificationPoster.m
new file mode 100644
index 0000000..e44ec0d
--- /dev/null
+++ b/Source/OCMock/OCMNotificationPoster.m
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMNotificationPoster.h"
+
+
+@implementation OCMNotificationPoster
+
+- (id)initWithNotification:(id)aNotification
+{
+	self = [super init];
+	notification = [aNotification retain];
+	return self;
+}
+
+- (void)dealloc
+{
+	[notification release];
+	[super dealloc];
+}
+
+- (void)handleInvocation:(NSInvocation *)anInvocation
+{
+	[[NSNotificationCenter defaultCenter] postNotification:notification];
+}
+
+
+@end
diff --git a/Source/OCMock/OCMObserverRecorder.h b/Source/OCMock/OCMObserverRecorder.h
new file mode 100644
index 0000000..5839cca
--- /dev/null
+++ b/Source/OCMock/OCMObserverRecorder.h
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMObserverRecorder : NSObject 
+{
+	NSNotification *recordedNotification;
+}
+
+- (void)notificationWithName:(NSString *)name object:(id)sender;
+
+- (BOOL)matchesNotification:(NSNotification *)aNotification;
+
+- (BOOL)argument:(id)expectedArg matchesArgument:(id)observedArg;
+
+@end
diff --git a/Source/OCMock/OCMObserverRecorder.m b/Source/OCMock/OCMObserverRecorder.m
new file mode 100644
index 0000000..66bef10
--- /dev/null
+++ b/Source/OCMock/OCMObserverRecorder.m
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import <OCMock/OCMConstraint.h>
+#import "NSInvocation+OCMAdditions.h"
+#import "OCMObserverRecorder.h"
+
+@interface NSObject(HCMatcherDummy)
+- (BOOL)matches:(id)item;
+@end
+
+#pragma mark -
+
+
+@implementation OCMObserverRecorder
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (void)dealloc
+{
+	[recordedNotification release];
+	[super dealloc];
+}
+
+
+#pragma mark  Recording
+
+- (void)notificationWithName:(NSString *)name object:(id)sender
+{
+	recordedNotification = [[NSNotification notificationWithName:name object:sender] retain];
+}
+
+- (void)notificationWithName:(NSString *)name object:(id)sender userInfo:(NSDictionary *)userInfo
+{
+	recordedNotification = [[NSNotification notificationWithName:name object:sender userInfo:userInfo] retain];
+}
+
+
+#pragma mark  Verification
+
+- (BOOL)matchesNotification:(NSNotification *)aNotification
+{
+	return [self argument:[recordedNotification name] matchesArgument:[aNotification name]] &&
+	[self argument:[recordedNotification object] matchesArgument:[aNotification object]] &&
+	[self argument:[recordedNotification userInfo] matchesArgument:[aNotification userInfo]];
+}
+
+- (BOOL)argument:(id)expectedArg matchesArgument:(id)observedArg
+{
+	if([expectedArg isKindOfClass:[OCMConstraint class]])
+	{	
+		return [expectedArg evaluate:observedArg];
+	}
+	else if([expectedArg conformsToProtocol:objc_getProtocol("HCMatcher")])
+	{
+		return [expectedArg matches:observedArg];
+	}
+	else if (expectedArg == observedArg)
+	{
+		return YES;
+	}
+	else if (expectedArg == nil || observedArg == nil)
+	{
+		return NO;
+	}
+	else
+	{
+		return [expectedArg isEqual:observedArg];
+	}
+}
+
+
+@end
diff --git a/Source/OCMock/OCMPassByRefSetter.h b/Source/OCMock/OCMPassByRefSetter.h
new file mode 100644
index 0000000..697881d
--- /dev/null
+++ b/Source/OCMock/OCMPassByRefSetter.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMPassByRefSetter : NSObject 
+{
+	id value;
+}
+
+- (id)initWithValue:(id)value;
+
+- (id)value;
+
+@end
diff --git a/Source/OCMock/OCMPassByRefSetter.m b/Source/OCMock/OCMPassByRefSetter.m
new file mode 100644
index 0000000..5cc15c5
--- /dev/null
+++ b/Source/OCMock/OCMPassByRefSetter.m
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMPassByRefSetter.h"
+
+
+@implementation OCMPassByRefSetter
+
+- (id)initWithValue:(id)aValue
+{
+	self = [super init];
+	value = [aValue retain];
+	return self;
+}
+
+- (void)dealloc
+{
+	[value release];
+	[super dealloc];
+}
+
+- (id)value
+{
+	return value;
+}
+
+@end
diff --git a/Source/OCMock/OCMRealObjectForwarder.h b/Source/OCMock/OCMRealObjectForwarder.h
new file mode 100644
index 0000000..9e35330
--- /dev/null
+++ b/Source/OCMock/OCMRealObjectForwarder.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2010-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMRealObjectForwarder : NSObject 
+{
+}
+
+- (void)handleInvocation:(NSInvocation *)anInvocation;
+
+@end
diff --git a/Source/OCMock/OCMRealObjectForwarder.m b/Source/OCMock/OCMRealObjectForwarder.m
new file mode 100644
index 0000000..e8caf17
--- /dev/null
+++ b/Source/OCMock/OCMRealObjectForwarder.m
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2010-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import "OCPartialMockObject.h"
+#import "OCMRealObjectForwarder.h"
+#import "OCMFunctions.h"
+
+
+@implementation OCMRealObjectForwarder
+
+- (void)handleInvocation:(NSInvocation *)anInvocation 
+{
+	id invocationTarget = [anInvocation target];
+
+    [anInvocation setSelector:OCMAliasForOriginalSelector([anInvocation selector])];
+	if ([invocationTarget isProxy])
+	{
+	    if (class_getInstanceMethod([invocationTarget mockObjectClass], @selector(realObject)))
+	    {
+	        // the method has been invoked on the mock, we need to change the target to the real object
+	        [anInvocation setTarget:[(OCPartialMockObject *)invocationTarget realObject]];
+	    }
+	    else
+	    {
+	        [NSException raise:NSInternalInconsistencyException
+	                    format:@"Method andForwardToRealObject can only be used with partial mocks and class methods."];
+	    }
+	}
+
+	[anInvocation invoke];
+}
+
+
+@end
diff --git a/Source/OCMock/OCMRecorder.h b/Source/OCMock/OCMRecorder.h
new file mode 100644
index 0000000..f56d2ca
--- /dev/null
+++ b/Source/OCMock/OCMRecorder.h
@@ -0,0 +1,39 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class OCMockObject;
+@class OCMInvocationMatcher;
+
+
+@interface OCMRecorder : NSProxy
+{
+    OCMockObject         *mockObject;
+    OCMInvocationMatcher *invocationMatcher;
+}
+
+- (instancetype)init;
+- (instancetype)initWithMockObject:(OCMockObject *)aMockObject;
+
+- (void)setMockObject:(OCMockObject *)aMockObject;
+
+- (OCMInvocationMatcher *)invocationMatcher;
+
+- (id)classMethod;
+- (id)ignoringNonObjectArgs;
+
+@end
diff --git a/Source/OCMock/OCMRecorder.m b/Source/OCMock/OCMRecorder.m
new file mode 100644
index 0000000..538b2f5
--- /dev/null
+++ b/Source/OCMock/OCMRecorder.m
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import "OCMRecorder.h"
+#import "OCMockObject.h"
+#import "OCMInvocationMatcher.h"
+#import "OCClassMockObject.h"
+
+@implementation OCMRecorder
+
+- (instancetype)init
+{
+    // no super, we're inheriting from NSProxy
+    return self;
+}
+
+- (instancetype)initWithMockObject:(OCMockObject *)aMockObject
+{
+    [self init];
+    [self setMockObject:aMockObject];
+	return self;
+}
+
+- (void)setMockObject:(OCMockObject *)aMockObject
+{
+    mockObject = aMockObject;
+}
+
+- (void)dealloc
+{
+    [invocationMatcher release];
+	[super dealloc];
+}
+
+- (NSString *)description
+{
+    return [invocationMatcher description];
+}
+
+- (OCMInvocationMatcher *)invocationMatcher
+{
+    return invocationMatcher;
+}
+
+
+#pragma mark  Modifying the matcher
+
+- (id)classMethod
+{
+    // should we handle the case where this is called with a mock that isn't a class mock?
+    [invocationMatcher setRecordedAsClassMethod:YES];
+    return self;
+}
+
+- (id)ignoringNonObjectArgs
+{
+    [invocationMatcher setIgnoreNonObjectArgs:YES];
+    return self;
+}
+
+
+#pragma mark  Recording the actual invocation
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
+{
+    if([invocationMatcher recordedAsClassMethod])
+        return [[(OCClassMockObject *)mockObject mockedClass] methodSignatureForSelector:aSelector];
+
+    NSMethodSignature *signature = [mockObject methodSignatureForSelector:aSelector];
+    if(signature == nil)
+    {
+        // if we're a working with a class mock and there is a class method, auto-switch
+        if(([object_getClass(mockObject) isSubclassOfClass:[OCClassMockObject class]]) &&
+           ([[(OCClassMockObject *)mockObject mockedClass] respondsToSelector:aSelector]))
+        {
+            [self classMethod];
+            signature = [self methodSignatureForSelector:aSelector];
+        }
+    }
+    return signature;
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation
+{
+	[anInvocation setTarget:nil];
+    [invocationMatcher setInvocation:anInvocation];
+}
+
+- (void)doesNotRecognizeSelector:(SEL)aSelector
+{
+    [NSException raise:NSInvalidArgumentException format:@"%@: cannot stub/expect/verify method '%@' because no such method exists in the mocked class.", mockObject, NSStringFromSelector(aSelector)];
+}
+
+
+@end
diff --git a/Source/OCMock/OCMReturnValueProvider.h b/Source/OCMock/OCMReturnValueProvider.h
new file mode 100644
index 0000000..d52e384
--- /dev/null
+++ b/Source/OCMock/OCMReturnValueProvider.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface OCMReturnValueProvider : NSObject 
+{
+	id	returnValue;
+}
+
+- (instancetype)initWithValue:(id)aValue;
+
+- (void)handleInvocation:(NSInvocation *)anInvocation;
+
+@end
diff --git a/Source/OCMock/OCMReturnValueProvider.m b/Source/OCMock/OCMReturnValueProvider.m
new file mode 100644
index 0000000..ed26ac0
--- /dev/null
+++ b/Source/OCMock/OCMReturnValueProvider.m
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "NSMethodSignature+OCMAdditions.h"
+#import "OCMReturnValueProvider.h"
+#import "OCMFunctions.h"
+
+
+@implementation OCMReturnValueProvider
+
+- (instancetype)initWithValue:(id)aValue
+{
+	self = [super init];
+	returnValue = [aValue retain];
+	return self;
+}
+
+- (void)dealloc
+{
+	[returnValue release];
+	[super dealloc];
+}
+
+- (void)handleInvocation:(NSInvocation *)anInvocation
+{
+    if(!OCMIsObjectType([[anInvocation methodSignature] methodReturnType]))
+    {
+        @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Expected invocation with object return type. Did you mean to use andReturnValue: instead?" userInfo:nil];
+    }
+    NSString *sel = NSStringFromSelector([anInvocation selector]);
+    if([sel hasPrefix:@"alloc"] || [sel hasPrefix:@"new"] || [sel hasPrefix:@"copy"] || [sel hasPrefix:@"mutableCopy"])
+    {
+        // methods that "create" an object return it with an extra retain count
+        [returnValue retain];
+    }
+	[anInvocation setReturnValue:&returnValue];
+}
+
+@end
diff --git a/Source/OCMock/OCMStubRecorder.h b/Source/OCMock/OCMStubRecorder.h
new file mode 100644
index 0000000..73b401f
--- /dev/null
+++ b/Source/OCMock/OCMStubRecorder.h
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2004-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMRecorder.h"
+
+
+@interface OCMStubRecorder : OCMRecorder
+
+- (id)andReturn:(id)anObject;
+- (id)andReturnValue:(NSValue *)aValue;
+- (id)andThrow:(NSException *)anException;
+- (id)andPost:(NSNotification *)aNotification;
+- (id)andCall:(SEL)selector onObject:(id)anObject;
+- (id)andDo:(void (^)(NSInvocation *invocation))block;
+- (id)andForwardToRealObject;
+
+@end
+
+
+@interface OCMStubRecorder (Properties)
+
+#define andReturn(aValue) _andReturn(({ typeof(aValue) _v = (aValue); [NSValue value:&_v withObjCType:@encode(typeof(_v))]; }))
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andReturn)(NSValue *);
+
+#define andThrow(anException) _andThrow(anException)
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andThrow)(NSException *);
+
+#define andPost(aNotification) _andPost(aNotification)
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andPost)(NSNotification *);
+
+#define andCall(anObject, aSelector) _andCall(anObject, aSelector)
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andCall)(id, SEL);
+
+#define andDo(aBlock) _andDo(aBlock)
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andDo)(void (^)(NSInvocation *));
+
+#define andForwardToRealObject() _andForwardToRealObject()
+@property (nonatomic, readonly) OCMStubRecorder *(^ _andForwardToRealObject)(void);
+
+@end
+
+
+
diff --git a/Source/OCMock/OCMStubRecorder.m b/Source/OCMock/OCMStubRecorder.m
new file mode 100644
index 0000000..4ca2ebb
--- /dev/null
+++ b/Source/OCMock/OCMStubRecorder.m
@@ -0,0 +1,187 @@
+/*
+ *  Copyright (c) 2004-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMStubRecorder.h"
+#import "OCClassMockObject.h"
+#import "OCMReturnValueProvider.h"
+#import "OCMBoxedReturnValueProvider.h"
+#import "OCMExceptionReturnValueProvider.h"
+#import "OCMIndirectReturnValueProvider.h"
+#import "OCMNotificationPoster.h"
+#import "OCMBlockCaller.h"
+#import "OCMRealObjectForwarder.h"
+#import "OCMFunctions.h"
+#import "OCMInvocationStub.h"
+
+
+@implementation OCMStubRecorder
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (id)init
+{
+    self = [super init];
+    invocationMatcher = [[OCMInvocationStub alloc] init];
+    return self;
+}
+
+- (OCMInvocationStub *)stub
+{
+    return (OCMInvocationStub *)invocationMatcher;
+}
+
+
+#pragma mark  Recording invocation actions
+
+- (id)andReturn:(id)anObject
+{
+	[[self stub] addInvocationAction:[[[OCMReturnValueProvider alloc] initWithValue:anObject] autorelease]];
+	return self;
+}
+
+- (id)andReturnValue:(NSValue *)aValue
+{
+    [[self stub] addInvocationAction:[[[OCMBoxedReturnValueProvider alloc] initWithValue:aValue] autorelease]];
+	return self;
+}
+
+- (id)andThrow:(NSException *)anException
+{
+    [[self stub] addInvocationAction:[[[OCMExceptionReturnValueProvider alloc] initWithValue:anException] autorelease]];
+	return self;
+}
+
+- (id)andPost:(NSNotification *)aNotification
+{
+    [[self stub] addInvocationAction:[[[OCMNotificationPoster alloc] initWithNotification:aNotification] autorelease]];
+	return self;
+}
+
+- (id)andCall:(SEL)selector onObject:(id)anObject
+{
+    [[self stub] addInvocationAction:[[[OCMIndirectReturnValueProvider alloc] initWithProvider:anObject andSelector:selector] autorelease]];
+	return self;
+}
+
+- (id)andDo:(void (^)(NSInvocation *))aBlock 
+{
+    [[self stub] addInvocationAction:[[[OCMBlockCaller alloc] initWithCallBlock:aBlock] autorelease]];
+	return self;
+}
+
+- (id)andForwardToRealObject
+{
+    [[self stub] addInvocationAction:[[[OCMRealObjectForwarder alloc] init] autorelease]];
+    return self;
+}
+
+
+#pragma mark Finishing recording
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation
+{
+    [super forwardInvocation:anInvocation];
+    [mockObject addStub:[self stub]];
+}
+
+
+@end
+
+
+@implementation OCMStubRecorder (Properties)
+
+@dynamic _andReturn;
+
+- (OCMStubRecorder *(^)(NSValue *))_andReturn
+{
+    id (^theBlock)(id) = ^ (NSValue *aValue)
+    {
+        if(OCMIsObjectType([aValue objCType]))
+        {
+            NSValue *objValue = nil;
+            [aValue getValue:&objValue];
+            return [self andReturn:objValue];
+        }
+        else
+        {
+            return [self andReturnValue:aValue];
+        }
+    };
+    return [[theBlock copy] autorelease];
+}
+
+
+@dynamic _andThrow;
+
+- (OCMStubRecorder *(^)(NSException *))_andThrow
+{
+    id (^theBlock)(id) = ^ (NSException * anException)
+    {
+        return [self andThrow:anException];
+    };
+    return [[theBlock copy] autorelease];
+}
+
+
+@dynamic _andPost;
+
+- (OCMStubRecorder *(^)(NSNotification *))_andPost
+{
+    id (^theBlock)(id) = ^ (NSNotification * aNotification)
+    {
+        return [self andPost:aNotification];
+    };
+    return [[theBlock copy] autorelease];
+}
+
+
+@dynamic _andCall;
+
+- (OCMStubRecorder *(^)(id, SEL))_andCall
+{
+    id (^theBlock)(id, SEL) = ^ (id anObject, SEL aSelector)
+    {
+        return [self andCall:aSelector onObject:anObject];
+    };
+    return [[theBlock copy] autorelease];
+}
+
+
+@dynamic _andDo;
+
+- (OCMStubRecorder *(^)(void (^)(NSInvocation *)))_andDo
+{
+    id (^theBlock)(void (^)(NSInvocation *)) = ^ (void (^ blockToCall)(NSInvocation *))
+    {
+        return [self andDo:blockToCall];
+    };
+    return [[theBlock copy] autorelease];
+}
+
+
+@dynamic _andForwardToRealObject;
+
+- (OCMStubRecorder *(^)(void))_andForwardToRealObject
+{
+    id (^theBlock)(void) = ^ (void)
+    {
+        return [self andForwardToRealObject];
+    };
+    return [[theBlock copy] autorelease];
+}
+
+
+@end
diff --git a/Source/OCMock/OCMVerifier.h b/Source/OCMock/OCMVerifier.h
new file mode 100644
index 0000000..7c95b01
--- /dev/null
+++ b/Source/OCMock/OCMVerifier.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCMRecorder.h"
+#import "OCMLocation.h"
+
+
+@interface OCMVerifier : OCMRecorder
+
+@property(retain) OCMLocation *location;
+
+@end
diff --git a/Source/OCMock/OCMVerifier.m b/Source/OCMock/OCMVerifier.m
new file mode 100644
index 0000000..8a1dcbe
--- /dev/null
+++ b/Source/OCMock/OCMVerifier.m
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import "OCMVerifier.h"
+#import "OCMockObject.h"
+#import "OCMLocation.h"
+#import "OCMInvocationMatcher.h"
+
+
+@implementation OCMVerifier
+
+- (id)init
+{
+    self = [super init];
+    invocationMatcher = [[OCMInvocationMatcher alloc] init];
+    return self;
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation
+{
+    [super forwardInvocation:anInvocation];
+    [mockObject verifyInvocation:invocationMatcher atLocation:self.location];
+}
+
+
+@end
diff --git a/Source/OCMock/OCMock.h b/Source/OCMock/OCMock.h
new file mode 100644
index 0000000..f0083b3
--- /dev/null
+++ b/Source/OCMock/OCMock.h
@@ -0,0 +1,84 @@
+/*
+ *  Copyright (c) 2004-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <OCMock/OCMockObject.h>
+#import <OCMock/OCMRecorder.h>
+#import <OCMock/OCMStubRecorder.h>
+#import <OCMock/OCMConstraint.h>
+#import <OCMock/OCMArg.h>
+#import <OCMock/OCMLocation.h>
+#import <OCMock/OCMMacroState.h>
+#import <OCMock/NSNotificationCenter+OCMAdditions.h>
+
+
+#define OCMClassMock(cls) [OCMockObject niceMockForClass:cls]
+
+#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls]
+
+#define OCMProtocolMock(protocol) [OCMockObject niceMockForProtocol:protocol]
+
+#define OCMStrictProtocolMock(protocol) [OCMockObject mockForProtocol:protocol]
+
+#define OCMPartialMock(obj) [OCMockObject partialMockForObject:obj]
+
+#define OCMObserverMock() [OCMockObject observerMock]
+
+
+#define OCMStub(invocation) \
+({ \
+    _OCMSilenceWarnings( \
+        [OCMMacroState beginStubMacro]; \
+        invocation; \
+        [OCMMacroState endStubMacro]; \
+    ); \
+})
+
+#define OCMExpect(invocation) \
+({ \
+    _OCMSilenceWarnings( \
+        [OCMMacroState beginExpectMacro]; \
+        invocation; \
+        [OCMMacroState endExpectMacro]; \
+    ); \
+})
+
+#define ClassMethod(invocation) \
+    _OCMSilenceWarnings( \
+        [[OCMMacroState globalState] switchToClassMethod]; \
+        invocation; \
+    );
+
+
+#define OCMVerifyAll(mock) [mock verifyAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
+
+#define OCMVerifyAllWithDelay(mock, delay) [mock verifyWithDelay:delay atLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
+
+#define OCMVerify(invocation) \
+({ \
+    _OCMSilenceWarnings( \
+        [OCMMacroState beginVerifyMacroAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]; \
+        invocation; \
+        [OCMMacroState endVerifyMacro]; \
+    ); \
+})
+
+#define _OCMSilenceWarnings(macro) \
+({ \
+    _Pragma("clang diagnostic push") \
+    _Pragma("clang diagnostic ignored \"-Wunused-value\"") \
+    macro \
+    _Pragma("clang diagnostic pop") \
+})
diff --git a/Source/OCMock/OCMockObject.h b/Source/OCMock/OCMockObject.h
new file mode 100644
index 0000000..63f2bae
--- /dev/null
+++ b/Source/OCMock/OCMockObject.h
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (c) 2004-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class OCMLocation;
+@class OCMInvocationStub;
+@class OCMStubRecorder;
+@class OCMInvocationMatcher;
+@class OCMInvocationExpectation;
+
+
+@interface OCMockObject : NSProxy
+{
+	BOOL			isNice;
+	BOOL			expectationOrderMatters;
+	NSMutableArray	*stubs;
+	NSMutableArray	*expectations;
+	NSMutableArray	*exceptions;
+    NSMutableArray  *invocations;
+}
+
++ (id)mockForClass:(Class)aClass;
++ (id)mockForProtocol:(Protocol *)aProtocol;
++ (id)partialMockForObject:(NSObject *)anObject;
+
++ (id)niceMockForClass:(Class)aClass;
++ (id)niceMockForProtocol:(Protocol *)aProtocol;
+
++ (id)observerMock;
+
+- (instancetype)init;
+
+- (void)setExpectationOrderMatters:(BOOL)flag;
+
+- (id)stub;
+- (id)expect;
+- (id)reject;
+
+- (id)verify;
+- (id)verifyAtLocation:(OCMLocation *)location;
+
+- (void)verifyWithDelay:(NSTimeInterval)delay;
+- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location;
+
+- (void)stopMocking;
+
+// internal use only
+
+- (void)addStub:(OCMInvocationStub *)aStub;
+- (void)addExpectation:(OCMInvocationExpectation *)anExpectation;
+
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation;
+- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation;
+- (BOOL)handleSelector:(SEL)sel;
+
+- (void)verifyInvocation:(OCMInvocationMatcher *)matcher;
+- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location;
+
+@end
+
diff --git a/Source/OCMock/OCMockObject.m b/Source/OCMock/OCMockObject.m
new file mode 100644
index 0000000..932c8ef
--- /dev/null
+++ b/Source/OCMock/OCMockObject.m
@@ -0,0 +1,352 @@
+/*
+ *  Copyright (c) 2004-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <OCMock/OCMockObject.h>
+#import "OCClassMockObject.h"
+#import "OCProtocolMockObject.h"
+#import "OCPartialMockObject.h"
+#import "OCObserverMockObject.h"
+#import "OCMStubRecorder.h"
+#import <OCMock/OCMLocation.h>
+#import "NSInvocation+OCMAdditions.h"
+#import "OCMInvocationMatcher.h"
+#import "OCMMacroState.h"
+#import "OCMFunctions.h"
+#import "OCMVerifier.h"
+#import "OCMInvocationExpectation.h"
+#import "OCMExpectationRecorder.h"
+
+
+@implementation OCMockObject
+
+#pragma mark  Class initialisation
+
++ (void)initialize
+{
+	if([[NSInvocation class] instanceMethodSignatureForSelector:@selector(getArgumentAtIndexAsObject:)] == NULL)
+		[NSException raise:NSInternalInconsistencyException format:@"** Expected method not present; the method getArgumentAtIndexAsObject: is not implemented by NSInvocation. If you see this exception it is likely that you are using the static library version of OCMock and your project is not configured correctly to load categories from static libraries. Did you forget to add the -ObjC linker flag?"];
+}
+
+
+#pragma mark  Factory methods
+
++ (id)mockForClass:(Class)aClass
+{
+	return [[[OCClassMockObject alloc] initWithClass:aClass] autorelease];
+}
+
++ (id)mockForProtocol:(Protocol *)aProtocol
+{
+	return [[[OCProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease];
+}
+
++ (id)partialMockForObject:(NSObject *)anObject
+{
+	return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease];
+}
+
+
++ (id)niceMockForClass:(Class)aClass
+{
+	return [self _makeNice:[self mockForClass:aClass]];
+}
+
++ (id)niceMockForProtocol:(Protocol *)aProtocol
+{
+	return [self _makeNice:[self mockForProtocol:aProtocol]];
+}
+
+
++ (id)_makeNice:(OCMockObject *)mock
+{
+	mock->isNice = YES;
+	return mock;
+}
+
+
++ (id)observerMock
+{
+	return [[[OCObserverMockObject alloc] init] autorelease];
+}
+
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (instancetype)init
+{
+	// no [super init], we're inheriting from NSProxy
+	expectationOrderMatters = NO;
+	stubs = [[NSMutableArray alloc] init];
+	expectations = [[NSMutableArray alloc] init];
+	exceptions = [[NSMutableArray alloc] init];
+    invocations = [[NSMutableArray alloc] init];
+    return self;
+}
+
+- (void)dealloc
+{
+	[stubs release];
+	[expectations release];
+	[exceptions release];
+    [invocations release];
+	[super dealloc];
+}
+
+- (NSString *)description
+{
+	return @"OCMockObject";
+}
+
+- (void)addStub:(OCMInvocationStub *)aStub
+{
+    [stubs addObject:aStub];
+}
+
+- (void)addExpectation:(OCMInvocationExpectation *)anExpectation
+{
+    [expectations addObject:anExpectation];
+}
+
+
+#pragma mark  Public API
+
+- (void)setExpectationOrderMatters:(BOOL)flag
+{
+    expectationOrderMatters = flag;
+}
+
+- (void)stopMocking
+{
+    // no-op for mock objects that are not class object or partial mocks
+}
+
+
+- (id)stub
+{
+	return [[[OCMStubRecorder alloc] initWithMockObject:self] autorelease];
+}
+
+- (id)expect
+{
+    return [[[OCMExpectationRecorder alloc] initWithMockObject:self] autorelease];
+}
+
+- (id)reject
+{
+	return [[self expect] never];
+}
+
+
+- (id)verify
+{
+    return [self verifyAtLocation:nil];
+}
+
+- (id)verifyAtLocation:(OCMLocation *)location
+{
+    NSMutableArray *unsatisfiedExpectations = [NSMutableArray array];
+    for(OCMInvocationExpectation *e in expectations)
+    {
+        if(![e isSatisfied])
+            [unsatisfiedExpectations addObject:e];
+    }
+
+	if([unsatisfiedExpectations count] == 1)
+	{
+        NSString *description = [NSString stringWithFormat:@"%@: expected method was not invoked: %@",
+         [self description], [[unsatisfiedExpectations objectAtIndex:0] description]];
+        OCMReportFailure(location, description);
+	}
+	else if([unsatisfiedExpectations count] > 0)
+	{
+		NSString *description = [NSString stringWithFormat:@"%@: %@ expected methods were not invoked: %@",
+         [self description], @([unsatisfiedExpectations count]), [self _stubDescriptions:YES]];
+        OCMReportFailure(location, description);
+	}
+
+	if([exceptions count] > 0)
+	{
+        NSString *description = [NSString stringWithFormat:@"%@: %@ (This is a strict mock failure that was ignored when it actually occured.)",
+         [self description], [[exceptions objectAtIndex:0] description]];
+        OCMReportFailure(location, description);
+	}
+
+    return [[[OCMVerifier alloc] initWithMockObject:self] autorelease];
+}
+
+
+- (void)verifyWithDelay:(NSTimeInterval)delay
+{
+    [self verifyWithDelay:delay atLocation:nil];
+}
+
+- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location
+{
+    NSTimeInterval step = 0.01;
+    while(delay > 0)
+    {
+        if([expectations count] == 0)
+            break;
+        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:step]];
+        delay -= step;
+        step *= 2;
+    }
+    [self verifyAtLocation:location];
+}
+
+
+#pragma mark Verify after running
+
+- (void)verifyInvocation:(OCMInvocationMatcher *)matcher
+{
+    [self verifyInvocation:matcher atLocation:nil];
+}
+
+- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location
+{
+    for(NSInvocation *invocation in invocations)
+    {
+        if([matcher matchesInvocation:invocation])
+            return;
+    }
+    NSString *description = [NSString stringWithFormat:@"%@: Method %@ was not invoked.",
+     [self description], [matcher description]];
+
+    OCMReportFailure(location, description);
+}
+
+
+#pragma mark  Handling invocations
+
+- (id)forwardingTargetForSelector:(SEL)aSelector
+{
+    if([OCMMacroState globalState] != nil)
+    {
+        OCMRecorder *recorder = [[OCMMacroState globalState] recorder];
+        [recorder setMockObject:self];
+        return recorder;
+    }
+    return nil;
+}
+
+
+- (BOOL)handleSelector:(SEL)sel
+{
+    for(OCMInvocationStub *recorder in stubs)
+        if([recorder matchesSelector:sel])
+            return YES;
+
+    return NO;
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation
+{
+    @try
+    {
+        if([self handleInvocation:anInvocation] == NO)
+            [self handleUnRecordedInvocation:anInvocation];
+    }
+    @catch(NSException *e)
+    {
+        [exceptions addObject:e];
+        [e raise];
+    }
+}
+
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation
+{
+    [invocations addObject:anInvocation];
+
+    OCMInvocationStub *stub = nil;
+    for(stub in stubs)
+    {
+        if([stub handleInvocation:anInvocation])
+            break;
+    }
+    if(stub == nil)
+        return NO;
+
+	if([expectations containsObject:stub])
+	{
+		if(expectationOrderMatters && ([expectations objectAtIndex:0] != stub))
+		{
+			[NSException raise:NSInternalInconsistencyException	format:@"%@: unexpected method invoked: %@\n\texpected:\t%@",  
+			 [self description], [stub description], [[expectations objectAtIndex:0] description]];
+			
+		}
+        if([(OCMInvocationExpectation *)stub isSatisfied])
+        {
+            [expectations removeObject:stub];
+            [stubs removeObject:stub];
+        }
+	}
+
+	return YES;
+}
+
+- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation
+{
+	if(isNice == NO)
+	{
+		[NSException raise:NSInternalInconsistencyException format:@"%@: unexpected method invoked: %@ %@",
+                        [self description], [anInvocation invocationDescription], [self _stubDescriptions:NO]];
+	}
+}
+
+- (void)doesNotRecognizeSelector:(SEL)aSelector __unused
+{
+    if([OCMMacroState globalState] != nil)
+    {
+        // we can't do anything clever with the macro state because we must raise an exception here
+        [NSException raise:NSInvalidArgumentException format:@"%@: Cannot stub/expect/verify method '%@' because no such method exists in the mocked class.",
+                        [self description], NSStringFromSelector(aSelector)];
+    }
+    else
+    {
+        [NSException raise:NSInvalidArgumentException format:@"-[%@ %@]: unrecognized selector sent to instance %p",
+                        [self description], NSStringFromSelector(aSelector), (void *)self];
+    }
+}
+
+
+#pragma mark  Helper methods
+
+- (NSString *)_stubDescriptions:(BOOL)onlyExpectations
+{
+	NSMutableString *outputString = [NSMutableString string];
+    for(OCMStubRecorder *stub in stubs)
+    {
+		NSString *prefix = @"";
+		
+		if(onlyExpectations)
+		{
+			if([expectations containsObject:stub] == NO)
+				continue;
+		}
+		else
+		{
+			if([expectations containsObject:stub])
+				prefix = @"expected:\t";
+			else
+				prefix = @"stubbed:\t";
+		}
+		[outputString appendFormat:@"\n\t%@%@", prefix, [stub description]];
+	}
+	return outputString;
+}
+
+
+@end
diff --git a/Source/OCMock/OCObserverMockObject.h b/Source/OCMock/OCObserverMockObject.h
new file mode 100644
index 0000000..444320e
--- /dev/null
+++ b/Source/OCMock/OCObserverMockObject.h
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class OCMLocation;
+
+
+@interface OCObserverMockObject : NSObject 
+{
+	BOOL		    expectationOrderMatters;
+	NSMutableArray  *recorders;
+    NSMutableArray  *centers;
+}
+
+- (void)setExpectationOrderMatters:(BOOL)flag;
+
+- (id)expect;
+
+- (void)verify;
+- (void)verifyAtLocation:(OCMLocation *)location;
+
+- (void)handleNotification:(NSNotification *)aNotification;
+
+// internal use
+
+- (void)autoRemoveFromCenter:(NSNotificationCenter *)aCenter;
+- (void)notificationWithName:(NSString *)name object:(id)sender;
+
+@end
diff --git a/Source/OCMock/OCObserverMockObject.m b/Source/OCMock/OCObserverMockObject.m
new file mode 100644
index 0000000..7c0e9cd
--- /dev/null
+++ b/Source/OCMock/OCObserverMockObject.m
@@ -0,0 +1,124 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCObserverMockObject.h"
+#import "OCMObserverRecorder.h"
+#import "OCMLocation.h"
+#import "OCMFunctions.h"
+
+
+@implementation OCObserverMockObject
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (id)init
+{
+	self = [super init];
+	recorders = [[NSMutableArray alloc] init];
+	centers = [[NSMutableArray alloc] init];
+	return self;
+}
+
+- (id)retain
+{
+    return [super retain];
+}
+
+- (void)dealloc
+{
+    for(NSNotificationCenter *c in centers)
+        [c removeObserver:self];
+    [centers release];
+	[recorders release];
+	[super dealloc];
+}
+
+- (NSString *)description
+{
+	return @"OCMockObserver";
+}
+
+- (void)setExpectationOrderMatters:(BOOL)flag
+{
+    expectationOrderMatters = flag;
+}
+
+- (void)autoRemoveFromCenter:(NSNotificationCenter *)aCenter
+{
+    [centers addObject:aCenter];
+}
+
+
+#pragma mark  Public API
+
+- (id)expect
+{
+	OCMObserverRecorder *recorder = [[[OCMObserverRecorder alloc] init] autorelease];
+	[recorders addObject:recorder];
+	return recorder;
+}
+
+- (void)verify
+{
+    [self verifyAtLocation:nil];
+}
+
+- (void)verifyAtLocation:(OCMLocation *)location
+{
+    if([recorders count] == 1)
+    {
+        NSString *description = [NSString stringWithFormat:@"%@: expected notification was not observed: %@",
+         [self description], [[recorders lastObject] description]];
+        OCMReportFailure(location, description);
+    }
+    else if([recorders count] > 0)
+    {
+        NSString *description = [NSString stringWithFormat:@"%@ : %@ expected notifications were not observed.",
+         [self description], @([recorders count])];
+        OCMReportFailure(location, description);
+    }
+}
+
+
+#pragma mark  Receiving recording requests via macro
+
+- (void)notificationWithName:(NSString *)name object:(id)sender
+{
+    [[self expect] notificationWithName:name object:sender];
+}
+
+
+#pragma mark  Receiving notifications
+
+- (void)handleNotification:(NSNotification *)aNotification
+{
+	NSUInteger i, limit;
+	
+	limit = expectationOrderMatters ? 1 : [recorders count];
+	for(i = 0; i < limit; i++)
+	{
+		if([[recorders objectAtIndex:i] matchesNotification:aNotification])
+		{
+			[recorders removeObjectAtIndex:i];
+			return;
+		}
+	}
+	[NSException raise:NSInternalInconsistencyException format:@"%@: unexpected notification observed: %@", [self description], 
+	  [aNotification description]];
+}
+
+
+@end
diff --git a/Source/OCMock/OCPartialMockObject.h b/Source/OCMock/OCPartialMockObject.h
new file mode 100644
index 0000000..de4febb
--- /dev/null
+++ b/Source/OCMock/OCPartialMockObject.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import "OCClassMockObject.h"
+
+@interface OCPartialMockObject : OCClassMockObject 
+{
+	NSObject	*realObject;
+}
+
+- (id)initWithObject:(NSObject *)anObject;
+
+- (NSObject *)realObject;
+
+@end
diff --git a/Source/OCMock/OCPartialMockObject.m b/Source/OCMock/OCPartialMockObject.m
new file mode 100644
index 0000000..0fc8776
--- /dev/null
+++ b/Source/OCMock/OCPartialMockObject.m
@@ -0,0 +1,216 @@
+/*
+ *  Copyright (c) 2009-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import "OCMockObject.h"
+#import "OCPartialMockObject.h"
+#import "NSMethodSignature+OCMAdditions.h"
+#import "NSObject+OCMAdditions.h"
+#import "OCMFunctions.h"
+#import "OCMInvocationStub.h"
+
+
+@implementation OCPartialMockObject
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (id)initWithObject:(NSObject *)anObject
+{
+    [self assertClassIsSupported:[anObject class]];
+	[super initWithClass:[anObject class]];
+	realObject = [anObject retain];
+    [self prepareObjectForInstanceMethodMocking];
+	return self;
+}
+
+- (void)dealloc
+{
+	[self stopMocking];
+	[super dealloc];
+}
+
+- (NSString *)description
+{
+	return [NSString stringWithFormat:@"OCPartialMockObject(%@)", NSStringFromClass(mockedClass)];
+}
+
+- (NSObject *)realObject
+{
+	return realObject;
+}
+
+#pragma mark  Helper methods
+
+- (void)assertClassIsSupported:(Class)class
+{
+    NSString *classname = NSStringFromClass(class);
+    NSString *reason = nil;
+    if([classname hasPrefix:@"__NSTagged"])
+        reason = [NSString stringWithFormat:@"OCMock does not support partially mocking tagged classes; got %@", classname];
+    else if([classname hasPrefix:@"__NSCF"])
+        reason = [NSString stringWithFormat:@"OCMock does not support partially mocking toll-free bridged classes; got %@", classname];
+
+    if(reason != nil)
+        [[NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil] raise];
+}
+
+
+#pragma mark  Extending/overriding superclass behaviour
+
+- (void)stopMocking
+{
+    if(realObject != nil)
+    {
+        OCMSetAssociatedMockForObject(nil, realObject);
+        object_setClass(realObject, [self mockedClass]);
+        [realObject release];
+        realObject = nil;
+    }
+    [super stopMocking];
+}
+
+- (void)addStub:(OCMInvocationStub *)aStub
+{
+    [super addStub:aStub];
+    if(![aStub recordedAsClassMethod])
+        [self setupForwarderForSelector:[[aStub recordedInvocation] selector]];
+}
+
+- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation
+{
+	[anInvocation invokeWithTarget:realObject];
+}
+
+
+#pragma mark  Subclass management
+
+- (void)prepareObjectForInstanceMethodMocking
+{
+    OCMSetAssociatedMockForObject(self, realObject);
+
+    /* dynamically create a subclass and set it as the class of the object */
+    Class subclass = OCMCreateSubclass(mockedClass, realObject);
+	object_setClass(realObject, subclass);
+
+    /* point forwardInvocation: of the object to the implementation in the mock */
+	Method myForwardMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardInvocationForRealObject:));
+	IMP myForwardIMP = method_getImplementation(myForwardMethod);
+    class_addMethod(subclass, @selector(forwardInvocation:), myForwardIMP, method_getTypeEncoding(myForwardMethod));
+
+    /* do the same for forwardingTargetForSelector, remember existing imp with alias selector */
+    Method myForwardingTargetMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardingTargetForSelectorForRealObject:));
+    IMP myForwardingTargetIMP = method_getImplementation(myForwardingTargetMethod);
+    IMP originalForwardingTargetIMP = [mockedClass instanceMethodForSelector:@selector(forwardingTargetForSelector:)];
+    class_addMethod(subclass, @selector(forwardingTargetForSelector:), myForwardingTargetIMP, method_getTypeEncoding(myForwardingTargetMethod));
+    class_addMethod(subclass, @selector(ocmock_replaced_forwardingTargetForSelector:), originalForwardingTargetIMP, method_getTypeEncoding(myForwardingTargetMethod));
+
+    /* We also override the -class method to return the original class */
+    Method myObjectClassMethod = class_getInstanceMethod([self mockObjectClass], @selector(classForRealObject));
+    const char *objectClassTypes = method_getTypeEncoding(myObjectClassMethod);
+    IMP myObjectClassImp = method_getImplementation(myObjectClassMethod);
+    class_addMethod(subclass, @selector(class), myObjectClassImp, objectClassTypes);
+
+    /* Adding forwarder for most instance methods to allow for verify after run */
+    NSArray *methodBlackList = @[@"class", @"forwardingTargetForSelector:", @"methodSignatureForSelector:", @"forwardInvocation:",
+            @"allowsWeakReference", @"retainWeakReference", @"isBlock"];
+    [NSObject enumerateMethodsInClass:mockedClass usingBlock:^(Class cls, SEL sel) {
+        if((cls == [NSObject class]) || (cls == [NSProxy class]))
+            return;
+        NSString *className = NSStringFromClass(cls);
+        NSString *selName = NSStringFromSelector(sel);
+        if(([className hasPrefix:@"NS"] || [className hasPrefix:@"UI"]) &&
+           ([selName hasPrefix:@"_"] || [selName hasSuffix:@"_"]))
+            return;
+        if([methodBlackList containsObject:selName])
+            return;
+        @try
+        {
+            [self setupForwarderForSelector:sel];
+        }
+        @catch(NSException *e)
+        {
+            // ignore for now
+        }
+    }];
+}
+
+- (void)setupForwarderForSelector:(SEL)sel
+{
+    SEL aliasSelector = OCMAliasForOriginalSelector(sel);
+    if(class_getInstanceMethod(object_getClass(realObject), aliasSelector) != NULL)
+        return;
+
+    Method originalMethod = class_getInstanceMethod(mockedClass, sel);
+	IMP originalIMP = method_getImplementation(originalMethod);
+    const char *types = method_getTypeEncoding(originalMethod);
+    /* Might be NULL if the selector is forwarded to another class */
+    // TODO: check the fallback implementation is actually sufficient
+    if(types == NULL)
+        types = ([[mockedClass instanceMethodSignatureForSelector:sel] fullObjCTypes]);
+
+    Class subclass = object_getClass([self realObject]);
+    IMP forwarderIMP = [mockedClass instanceMethodForwarderForSelector:sel];
+    class_replaceMethod(subclass, sel, forwarderIMP, types);
+	class_addMethod(subclass, aliasSelector, originalIMP, types);
+}
+
+
+// Implementation of the -class method; return the Class that was reported with [realObject class] prior to mocking
+- (Class)classForRealObject
+{
+    // in here "self" is a reference to the real object, not the mock
+    OCPartialMockObject *mock = OCMGetAssociatedMockForObject(self);
+    if(mock == nil)
+        [NSException raise:NSInternalInconsistencyException format:@"No partial mock for object %p", self];
+    return [mock mockedClass];
+}
+
+
+- (id)forwardingTargetForSelectorForRealObject:(SEL)sel
+{
+	// in here "self" is a reference to the real object, not the mock
+    OCPartialMockObject *mock = OCMGetAssociatedMockForObject(self);
+    if(mock == nil)
+        [NSException raise:NSInternalInconsistencyException format:@"No partial mock for object %p", self];
+    if([mock handleSelector:sel])
+        return self;
+
+    return [self ocmock_replaced_forwardingTargetForSelector:sel];
+}
+
+//  Make the compiler happy in -forwardingTargetForSelectorForRealObject: because it can't find the message…
+- (id)ocmock_replaced_forwardingTargetForSelector:(SEL)sel
+{
+    return nil;
+}
+
+
+- (void)forwardInvocationForRealObject:(NSInvocation *)anInvocation
+{
+	// in here "self" is a reference to the real object, not the mock
+    OCPartialMockObject *mock = OCMGetAssociatedMockForObject(self);
+    if(mock == nil)
+        [NSException raise:NSInternalInconsistencyException format:@"No partial mock for object %p", self];
+
+	if([mock handleInvocation:anInvocation] == NO)
+    {
+        [anInvocation setSelector:OCMAliasForOriginalSelector([anInvocation selector])];
+        [anInvocation invoke];
+    }
+}
+
+
+@end
diff --git a/Source/OCMock/OCProtocolMockObject.h b/Source/OCMock/OCProtocolMockObject.h
new file mode 100644
index 0000000..18cc38f
--- /dev/null
+++ b/Source/OCMock/OCProtocolMockObject.h
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (c) 2005-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <OCMock/OCMockObject.h>
+
+@interface OCProtocolMockObject : OCMockObject 
+{
+	Protocol	*mockedProtocol;
+}
+
+- (id)initWithProtocol:(Protocol *)aProtocol;
+
+@end
+
diff --git a/Source/OCMock/OCProtocolMockObject.m b/Source/OCMock/OCProtocolMockObject.m
new file mode 100644
index 0000000..2538057
--- /dev/null
+++ b/Source/OCMock/OCProtocolMockObject.m
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (c) 2005-2014 Erik Doernenburg and contributors
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use these files except in compliance with the License. You may obtain
+ *  a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *  License for the specific language governing permissions and limitations
+ *  under the License.
+ */
+
+#import <objc/runtime.h>
+#import "NSMethodSignature+OCMAdditions.h"
+#import "OCProtocolMockObject.h"
+
+@implementation OCProtocolMockObject
+
+#pragma mark  Initialisers, description, accessors, etc.
+
+- (id)initWithProtocol:(Protocol *)aProtocol
+{
+	[super init];
+	mockedProtocol = aProtocol;
+	return self;
+}
+
+- (NSString *)description
+{
+    const char* name = protocol_getName(mockedProtocol);
+    return [NSString stringWithFormat:@"OCMockObject(%s)", name];
+}
+
+#pragma mark  Proxy API
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
+{
+	struct objc_method_description methodDescription = protocol_getMethodDescription(mockedProtocol, aSelector, YES, YES);
+    if(methodDescription.name == NULL) 
+	{
+        methodDescription = protocol_getMethodDescription(mockedProtocol, aSelector, NO, YES);
+    }
+    if(methodDescription.name == NULL) 
+	{
+        return nil;
+    }
+	return [NSMethodSignature signatureWithObjCTypes:methodDescription.types];
+}
+
+- (BOOL)conformsToProtocol:(Protocol *)aProtocol
+{
+    return protocol_conformsToProtocol(mockedProtocol, aProtocol);
+}
+
+- (BOOL)respondsToSelector:(SEL)selector
+{
+    return ([self methodSignatureForSelector:selector] != nil);
+}
+
+@end