Skip to content

Commit

Permalink
Implemented basic merging of method groups from categories and extens…
Browse files Browse the repository at this point in the history
…ions.
  • Loading branch information
tomaz committed Jan 25, 2014
1 parent 69ba697 commit 8be86da
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 38 deletions.
154 changes: 154 additions & 0 deletions AppledocTests/Processing/MergeKnownObjectsTaskTests.mm
@@ -0,0 +1,154 @@
//
// MergeKnownObjectsTaskTests.m
// appledoc
//
// Created by Tomaz Kragelj on 7/12/12.
// Copyright (c) 2012 Tomaz Kragelj. All rights reserved.
//

#import "StoreMocks.h"
#import "MergeKnownObjectsTask.h"
#import "TestCaseBase.hh"

#define GBSections [comment sourceSections]

#pragma mark -

static void runWithTask(id store, id settings, void(^handler)(MergeKnownObjectsTask *task, id store, id settings)) {
MergeKnownObjectsTask *task = [[MergeKnownObjectsTask alloc] init];
task.settings = settings ? settings : mock([GBSettings class]);
task.store = store ? store : mock([Store class]);
handler(task, task.store, task.settings);
[task release];
}

static void addGroups(id object, NSDictionary *groups) {
[StoreMocks add:groups asMethodGroupsOf:object];
[StoreMocks add:groups asMembersOf:object];
}

static id createMethod(NSString *selector) {
return [StoreMocks mockMethod:selector block:^(id object) { }];
}

static id createProperty(NSString *selector) {
return [StoreMocks mockProperty:selector block:^(id object) { }];
}

static id createCategory(NSString *name, id extendingClass) {
return [StoreMocks mockCategory:name onClass:extendingClass block:^(id object) { }];
}

#define GBGroupsCount(c) \
extendee.interfaceMethodGroups.count should equal(c)
#define GBGroupMethod(i,j,o) \
[extendee.interfaceMethodGroups[i] methodGroupMethods][j] should equal(o)
#define GBGroup(i,n,...) do { \
id methods[] = { __VA_ARGS__ }; \
NSUInteger count = sizeof(methods) / sizeof(id); \
[extendee.interfaceMethodGroups[i] nameOfMethodGroup] should equal(n); \
[[extendee.interfaceMethodGroups[i] methodGroupMethods] count] should equal(count); \
for (NSUInteger j=0; j<count; j++) { \
id method = methods[j]; \
GBGroupMethod(i,j,method); \
} \
} while(NO);

#define GBClassMethods() extendee.interfaceClassMethods
#define GBInstanceMethods() extendee.interfaceInstanceMethods
#define GBProperties() extendee.interfaceProperties

#define GBMembersCount(m,c) [m count] should equal(c)
#define GBMember(m,i,o) m[i] should equal(o)
#define GBMembers(m,...) do { \
id members[] = { __VA_ARGS__ }; \
NSUInteger count = sizeof(members) / sizeof(id); \
GBMembersCount(m,count); \
for (NSUInteger i=0; i<count; i++) { \
id member = members[i]; \
GBMember(m,i,member); \
} \
} while (NO)

#pragma mark -

TEST_BEGIN(MergeKnownObjectsTaskTests)

describe(@"method groups:", ^{
__block id store;
__block id settings;

beforeEach(^{
settings = mock([GBSettings class]);
store = mock([Store class]);
});

sharedExamplesFor(@"examples", ^(NSDictionary *info) {
#define GBCategory() info[@"category"]; [StoreMocks add:extendee asExtendedClassOf:category]
it(@"should merge class & instance methods and properties to empty class", ^{
runWithTask(store, settings, ^(MergeKnownObjectsTask *task, id store, id settings) {
// setup
ClassInfo *extendee = [StoreMocks createClass:^(ClassInfo *object) { }];
id category = GBCategory();
id classMethod = createMethod(@"+method");
id instanceMethod = createMethod(@"-method");
id property = createProperty(@"property");
addGroups(category, @{ @"group1":@[classMethod,instanceMethod,property] });
// execute
[task runTask];
// verify
GBGroupsCount(1);
GBGroup(0, @"group1", classMethod, instanceMethod, property);
GBMembers(GBClassMethods(), classMethod);
GBMembers(GBInstanceMethods(), instanceMethod);
GBMembers(GBProperties(), property);
});
});

it(@"should merge class & instance methods and properties to non-empty class", ^{
runWithTask(store, settings, ^(MergeKnownObjectsTask *task, id store, id settings) {
// setup
ClassInfo *extendee = [StoreMocks createClass:^(ClassInfo *object) {
[object.interfaceClassMethods addObject:[StoreMocks createMethod:@"+method1" block:^(MethodInfo *object) { }]];
[object.interfaceInstanceMethods addObject:[StoreMocks createMethod:@"-method1" block:^(MethodInfo *object) { }] ];
[object.interfaceProperties addObject:[StoreMocks createProperty:@"property1" block:^(PropertyInfo *object) { }] ];
}];
id category = GBCategory();
id categoryClassMethod = createMethod(@"+method");
id categoryInstanceMethod = createMethod(@"-method");
id categoryProperty = createProperty(@"property");
addGroups(category, @{ @"group1":@[categoryClassMethod,categoryInstanceMethod,categoryProperty] });
// execute
[task runTask];
// verify
GBGroupsCount(1);
GBGroup(0, @"group1", categoryClassMethod, categoryInstanceMethod, categoryProperty);
GBMembers(GBClassMethods(), extendee.interfaceClassMethods[0], categoryClassMethod);
GBMembers(GBInstanceMethods(), extendee.interfaceInstanceMethods[0], categoryInstanceMethod);
GBMembers(GBProperties(), extendee.interfaceProperties[0], categoryProperty);
});
});
});

describe(@"extensions:", ^{
beforeEach(^{
id extension = createCategory(@"", nil);
[[SpecHelper specHelper] sharedExampleContext][@"store"] = store;
[[SpecHelper specHelper] sharedExampleContext][@"category"] = extension;
[given([store storeExtensions]) willReturn:[@[ extension ] mutableCopy]];
});
itShouldBehaveLike(@"examples");
});

describe(@"categoried:", ^{
beforeEach(^{
id category = createCategory(@"category", nil);
[[SpecHelper specHelper] sharedExampleContext][@"store"] = store;
[[SpecHelper specHelper] sharedExampleContext][@"category"] = category;
[given([store storeCategories]) willReturn:[@[ category ] mutableCopy]];
});
itShouldBehaveLike(@"examples");
});
});

TEST_END
2 changes: 2 additions & 0 deletions AppledocTests/Store/MethodInfoTests.mm
Expand Up @@ -104,6 +104,7 @@ static void runWithMethodInfoWithRegistrar(void(^handler)(MethodInfo *info, Stor
// execute & verify
info.isClassMethod should equal(YES);
info.isInstanceMethod should equal(NO);
info.isProperty should equal(NO);
});
});

Expand All @@ -114,6 +115,7 @@ static void runWithMethodInfoWithRegistrar(void(^handler)(MethodInfo *info, Stor
// execute & verify
info.isClassMethod should equal(NO);
info.isInstanceMethod should equal(YES);
info.isProperty should equal(NO);
});
});
});
Expand Down
11 changes: 11 additions & 0 deletions AppledocTests/Store/PropertyInfoTests.mm
Expand Up @@ -30,6 +30,17 @@ static void runWithPropertyInfo(void(^handler)(PropertyInfo *info)) {
});
});

describe(@"method and property info:", ^{
it(@"should return YES for property, NO for method", ^{
runWithPropertyInfo(^(PropertyInfo *info) {
// execute & verify
info.isProperty should equal(YES);
info.isClassMethod should equal(NO);
info.isInstanceMethod should equal(NO);
});
});
});

describe(@"getter and setter selectors:", ^{
it(@"should return default name if no attribute is given", ^{
runWithPropertyInfo(^(PropertyInfo *info) {
Expand Down
17 changes: 10 additions & 7 deletions AppledocTests/TestingBase/StoreMocks.h
Expand Up @@ -12,32 +12,35 @@ typedef void(^GBCreateObjectBlock)(id object);

@interface StoreMocks : NSObject

+ (ObjectLinkInfo *)link:(id)nameOrObject;

+ (InterfaceInfoBase *)createInterface:(void(^)(InterfaceInfoBase *object))handler;
+ (ClassInfo *)createClass:(void(^)(ClassInfo *object))handler;
+ (CategoryInfo *)createCategory:(void(^)(CategoryInfo *object))handler;
+ (ProtocolInfo *)createProtocol:(void(^)(ProtocolInfo *object))handler;

+ (MethodInfo *)createMethod:(NSString *)uniqueID;
+ (MethodInfo *)createMethod:(NSString *)uniqueID block:(void(^)(MethodInfo *object))handler;
+ (PropertyInfo *)createProperty:(NSString *)uniqueID;
+ (PropertyInfo *)createProperty:(NSString *)uniqueID block:(void(^)(PropertyInfo *object))handler;
+ (ObjectLinkInfo *)link:(id)nameOrObject;
+ (MethodGroupInfo *)createMethodGroup:(NSString *)name block:(void(^)(MethodGroupInfo *object))handler;

+ (id)mockClass:(NSString *)name block:(GBCreateObjectBlock)handler;
+ (id)mockCategory:(NSString *)name onClass:(NSString *)className block:(GBCreateObjectBlock)handler;
+ (id)mockCategory:(NSString *)name onClass:(id)classNameOrObject block:(GBCreateObjectBlock)handler;
+ (id)mockProtocol:(NSString *)name block:(GBCreateObjectBlock)handler;

+ (id)mockMethod:(NSString *)uniqueID;
+ (id)mockMethod:(NSString *)uniqueID block:(GBCreateObjectBlock)handler;
+ (id)mockProperty:(NSString *)uniqueID;
+ (id)mockProperty:(NSString *)uniqueID block:(GBCreateObjectBlock)handler;
+ (id)mockMethodGroup:(NSString *)name block:(GBCreateObjectBlock)handler;

+ (void)addMockCommentTo:(id)objectOrMock;
+ (void)add:(id)classOrName asExtendedClassOf:(id)categoryOrMock;
+ (void)add:(id)classOrMock asDerivedClassFrom:(id)baseOrMock;
+ (void)add:(id)objectOrMock asAdopting:(id)protocolOrMock;
+ (void)add:(id)methodOrMock asClassMethodOf:(id)interfaceOrMock;
+ (void)add:(id)methodOrMock asInstanceMethodOf:(id)interfaceOrMock;
+ (void)add:(id)propertyOrMock asPropertyOf:(id)interfaceOrMock;
+ (void)add:(id)memberOrArray asMembersOfGroup:(id)groupOrMock;
+ (void)add:(NSDictionary *)groups asMethodGroupsOf:(id)interfaceOrMock;
+ (void)add:(NSDictionary *)groups asMembersOf:(id)interfaceOrMock;

@end

Expand All @@ -50,7 +53,7 @@ typedef void(^GBCreateObjectBlock)(id object);
#pragma mark -

@interface CategoryInfo (UnitTestsMocks)
- (void)extend:(NSString *)name;
- (void)extend:(id)nameOrClass;
@end

#pragma mark -
Expand Down

0 comments on commit 8be86da

Please sign in to comment.