aboutsummaryrefslogtreecommitdiff
path: root/DebugUtils/GTMDebugSelectorValidation.h
diff options
context:
space:
mode:
authorGravatar thomasvl <thomasvl@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-04-14 17:21:02 +0000
committerGravatar thomasvl <thomasvl@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-04-14 17:21:02 +0000
commitcdf070c8d76ffc4eaa24e8671756cbbe9ceb2890 (patch)
treefaa9ae3a72a6591d6a6add7ceed7f91e92ade11f /DebugUtils/GTMDebugSelectorValidation.h
parent0aaecac6ff2bc89e58a0c8c6d6ad62e02fb2b011 (diff)
See the ReleaseNotes for the full details, highlights:
- bug fixes - code coverage support - more complete unittests - full support for unittesting UIs - support for the iphone sdk (include ui unittesting)
Diffstat (limited to 'DebugUtils/GTMDebugSelectorValidation.h')
-rw-r--r--DebugUtils/GTMDebugSelectorValidation.h86
1 files changed, 86 insertions, 0 deletions
diff --git a/DebugUtils/GTMDebugSelectorValidation.h b/DebugUtils/GTMDebugSelectorValidation.h
new file mode 100644
index 0000000..b3f1e73
--- /dev/null
+++ b/DebugUtils/GTMDebugSelectorValidation.h
@@ -0,0 +1,86 @@
+//
+// GTMDebugSelectorValidation.h
+//
+// This file should only be included within an implimation file. In any
+// function that takes an object and selector to invoke, you should call:
+//
+// GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, @encode(arg1type), ..., NULL)
+//
+// This will then validate that the selector is defined and using the right
+// type(s), this can help catch errors much earlier then waiting for the
+// selector to actually fire (and in the case of error selectors, might never
+// really be tested until in the field).
+//
+// Copyright 2007-2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file 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.
+//
+
+#if DEBUG
+
+#import <stdarg.h>
+#import "GTMDefines.h"
+
+static void GTMAssertSelectorNilOrImplementedWithArguments(id obj, SEL sel, ...) {
+
+ // verify that the object's selector is implemented with the proper
+ // number and type of arguments
+ va_list argList;
+ va_start(argList, sel);
+
+ if (obj && sel) {
+ // check that the selector is implemented
+ if (![obj respondsToSelector:sel]) {
+ _GTMDevAssert(NO,
+ @"\"%@\" selector \"%@\" is unimplemented or misnamed",
+ NSStringFromClass([obj class]),
+ NSStringFromSelector(sel));
+ } else {
+ const char *expectedArgType;
+ int argCount = 2; // skip self and _cmd
+ NSMethodSignature *sig = [obj methodSignatureForSelector:sel];
+
+ // check that each expected argument is present and of the correct type
+ while ((expectedArgType = va_arg(argList, const char*)) != 0) {
+
+ if ([sig numberOfArguments] > argCount) {
+ const char *foundArgType = [sig getArgumentTypeAtIndex:argCount];
+
+ _GTMDevAssert(0 == strncmp(foundArgType, expectedArgType, strlen(expectedArgType)),
+ @"\"%@\" selector \"%@\" argument %d should be type %s",
+ NSStringFromClass([obj class]),
+ NSStringFromSelector(sel),
+ (argCount - 2),
+ expectedArgType);
+ }
+ argCount++;
+ }
+
+ // check that the proper number of arguments are present in the selector
+ _GTMDevAssert(argCount == [sig numberOfArguments],
+ @"\"%@\" selector \"%@\" should have %d arguments",
+ NSStringFromClass([obj class]),
+ NSStringFromSelector(sel),
+ (argCount - 2));
+ }
+ }
+
+ va_end(argList);
+}
+
+#else // DEBUG
+
+// make it go away if not debug
+#define GTMAssertSelectorNilOrImplementedWithArguments(obj, sel, ...) do { } while (0)
+
+#endif // DEBUG