Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
catch_objc.hpp
Go to the documentation of this file.
1/*
2 * Created by Phil on 14/11/2010.
3 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4 *
5 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 */
8#ifndef TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
9#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
10
11#include "catch_objc_arc.hpp"
12
13#import <objc/runtime.h>
14
15#include <string>
16
17// NB. Any general catch headers included here must be included
18// in catch.hpp first to make sure they are included by the single
19// header for non obj-usage
21#include "catch_string_manip.h"
22#include "catch_tostring.h"
23
25// This protocol is really only here for (self) documenting purposes, since
26// all its methods are optional.
27@protocol OcFixture
28
29@optional
30
31-(void) setUp;
32-(void) tearDown;
33
34@end
35
36namespace Catch {
37
38 class OcMethod : public ITestInvoker {
39
40 public:
41 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
42
43 virtual void invoke() const {
44 id obj = [[m_cls alloc] init];
45
46 performOptionalSelector( obj, @selector(setUp) );
47 performOptionalSelector( obj, m_sel );
48 performOptionalSelector( obj, @selector(tearDown) );
49
50 arcSafeRelease( obj );
51 }
52 private:
53 virtual ~OcMethod() {}
54
55 Class m_cls;
56 SEL m_sel;
57 };
58
59 namespace Detail{
60
61
62 inline std::string getAnnotation( Class cls,
63 std::string const& annotationName,
64 std::string const& testCaseName ) {
65 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
66 SEL sel = NSSelectorFromString( selStr );
67 arcSafeRelease( selStr );
68 id value = performOptionalSelector( cls, sel );
69 if( value )
70 return [(NSString*)value UTF8String];
71 return "";
72 }
73 }
74
75 inline std::size_t registerTestMethods() {
76 std::size_t noTestMethods = 0;
77 int noClasses = objc_getClassList( nullptr, 0 );
78
79 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
80 objc_getClassList( classes, noClasses );
81
82 for( int c = 0; c < noClasses; c++ ) {
83 Class cls = classes[c];
84 {
85 u_int count;
86 Method* methods = class_copyMethodList( cls, &count );
87 for( u_int m = 0; m < count ; m++ ) {
88 SEL selector = method_getName(methods[m]);
89 std::string methodName = sel_getName(selector);
90 if( startsWith( methodName, "Catch_TestCase_" ) ) {
91 std::string testCaseName = methodName.substr( 15 );
92 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
93 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
94 const char* className = class_getName( cls );
95
96 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
97 noTestMethods++;
98 }
99 }
100 free(methods);
101 }
102 }
103 return noTestMethods;
104 }
105
106#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
107
108 namespace Matchers {
109 namespace Impl {
110 namespace NSStringMatchers {
111
112 struct StringHolder : MatcherBase<NSString*>{
113 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
114 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
115 StringHolder() {
116 arcSafeRelease( m_substr );
117 }
118
119 bool match( NSString* const& str ) const override {
120 return false;
121 }
122
123 NSString* CATCH_ARC_STRONG m_substr;
124 };
125
126 struct Equals : StringHolder {
127 Equals( NSString* substr ) : StringHolder( substr ){}
128
129 bool match( NSString* const& str ) const override {
130 return (str != nil || m_substr == nil ) &&
131 [str isEqualToString:m_substr];
132 }
133
134 std::string describe() const override {
135 return "equals string: " + Catch::Detail::stringify( m_substr );
136 }
137 };
138
139 struct Contains : StringHolder {
140 Contains( NSString* substr ) : StringHolder( substr ){}
141
142 bool match( NSString* const& str ) const override {
143 return (str != nil || m_substr == nil ) &&
144 [str rangeOfString:m_substr].location != NSNotFound;
145 }
146
147 std::string describe() const override {
148 return "contains string: " + Catch::Detail::stringify( m_substr );
149 }
150 };
151
152 struct StartsWith : StringHolder {
153 StartsWith( NSString* substr ) : StringHolder( substr ){}
154
155 bool match( NSString* const& str ) const override {
156 return (str != nil || m_substr == nil ) &&
157 [str rangeOfString:m_substr].location == 0;
158 }
159
160 std::string describe() const override {
161 return "starts with: " + Catch::Detail::stringify( m_substr );
162 }
163 };
164 struct EndsWith : StringHolder {
165 EndsWith( NSString* substr ) : StringHolder( substr ){}
166
167 bool match( NSString* const& str ) const override {
168 return (str != nil || m_substr == nil ) &&
169 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
170 }
171
172 std::string describe() const override {
173 return "ends with: " + Catch::Detail::stringify( m_substr );
174 }
175 };
176
177 } // namespace NSStringMatchers
178 } // namespace Impl
179
180 inline Impl::NSStringMatchers::Equals
181 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
182
183 inline Impl::NSStringMatchers::Contains
184 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
185
186 inline Impl::NSStringMatchers::StartsWith
187 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
188
189 inline Impl::NSStringMatchers::EndsWith
190 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
191
192 } // namespace Matchers
193
194 using namespace Matchers;
195
196#endif // CATCH_CONFIG_DISABLE_MATCHERS
197
198} // namespace Catch
199
201#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
202#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
203+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
204{ \
205return @ name; \
206} \
207+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
208{ \
209return @ desc; \
210} \
211-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
212
213#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
214
215#endif // TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
void arcSafeRelease(NSObject *obj)
id performOptionalSelector(id obj, SEL sel)
#define CATCH_UNSAFE_UNRETAINED
#define CATCH_ARC_STRONG
std::string name
OcMethod(Class cls, SEL sel)
virtual void invoke() const
#define Method
int * count
std::string getAnnotation(Class cls, std::string const &annotationName, std::string const &testCaseName)
std::string stringify(const T &e)
StdString::StartsWithMatcher StartsWith(std::string const &str, CaseSensitive::Choice caseSensitivity)
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity)
StdString::EndsWithMatcher EndsWith(std::string const &str, CaseSensitive::Choice caseSensitivity)
StdString::ContainsMatcher Contains(std::string const &str, CaseSensitive::Choice caseSensitivity)
TestCase makeTestCase(ITestInvoker *_testCase, std::string const &_className, NameAndTags const &nameAndTags, SourceLineInfo const &_lineInfo)
IMutableRegistryHub & getMutableRegistryHub()
bool startsWith(std::string const &s, std::string const &prefix)
std::size_t registerTestMethods()
#define value
Definition pkcs11.h:157
virtual void registerTest(TestCase const &testInfo)=0