main
  1//
  2// Licensed under the terms in License.txt
  3//
  4// Copyright 2010 Allen Ding. All rights reserved.
  5//
  6
  7#import "KWMessageTracker.h"
  8#import "KWMessagePattern.h"
  9#import "NSObject+KiwiStubAdditions.h"
 10
 11@interface KWMessageTracker()
 12
 13#pragma mark -
 14#pragma mark Properties
 15
 16@property (nonatomic, readwrite) NSUInteger receivedCount;
 17
 18@end
 19
 20@implementation KWMessageTracker
 21
 22#pragma mark -
 23#pragma mark Initializing
 24
 25- (id)initWithSubject:(id)anObject messagePattern:(KWMessagePattern *)aMessagePattern countType:(KWCountType)aCountType count:(NSUInteger)aCount {
 26    if ((self = [super init])) {
 27        subject = [anObject retain];
 28        messagePattern = [aMessagePattern retain];
 29        countType = aCountType;
 30        count = aCount;
 31        [anObject addMessageSpy:self forMessagePattern:messagePattern];
 32    }
 33
 34    return self;
 35}
 36
 37+ (id)messageTrackerWithSubject:(id)anObject messagePattern:(KWMessagePattern *)aMessagePattern countType:(KWCountType)aCountType count:(NSUInteger)aCount {
 38    return [[[self alloc] initWithSubject:anObject messagePattern:aMessagePattern countType:aCountType count:aCount] autorelease];
 39}
 40
 41- (void)dealloc {
 42    [subject release];
 43    [messagePattern release];
 44    [super dealloc];
 45}
 46
 47#pragma mark -
 48#pragma mark Properties
 49
 50@synthesize subject;
 51@synthesize messagePattern;
 52@synthesize countType;
 53@synthesize count;
 54@synthesize receivedCount;
 55
 56#pragma mark -
 57#pragma mark Spying on Messages
 58
 59- (void)object:(id)anObject didReceiveInvocation:(NSInvocation *)anInvocation {
 60    if (![self.messagePattern matchesInvocation:anInvocation])
 61        return;
 62
 63    ++self.receivedCount;
 64}
 65
 66#pragma mark -
 67#pragma mark Stopping Tracking
 68
 69- (void)stopTracking {
 70    [self.subject removeMessageSpy:self forMessagePattern:self.messagePattern];
 71}
 72
 73#pragma mark -
 74#pragma mark Getting Message Tracker Status
 75
 76- (BOOL)succeeded {
 77    switch (self.countType) {
 78        case KWCountTypeExact:
 79            return self.receivedCount == self.count;
 80        case KWCountTypeAtLeast:
 81            return self.receivedCount >= self.count;
 82        case KWCountTypeAtMost:
 83            return self.receivedCount <= self.count;
 84        default:
 85            break;
 86    }
 87
 88    assert(0 && "should never reach here");
 89    return NO;
 90}
 91
 92#pragma mark -
 93#pragma mark Getting Phrases
 94
 95- (NSString *)phraseForCount:(NSUInteger)aCount {
 96    if (aCount == 1)
 97        return @"1 time";
 98
 99    return [NSString stringWithFormat:@"%d times", (int)aCount];
100}
101
102- (NSString *)expectedCountPhrase {
103    NSString *countPhrase = [self phraseForCount:self.count];
104
105    switch (self.countType) {
106        case KWCountTypeExact:
107            return [NSString stringWithFormat:@"exactly %@", countPhrase];
108        case KWCountTypeAtLeast:
109            return [NSString stringWithFormat:@"at least %@", countPhrase];
110        case KWCountTypeAtMost:
111            return [NSString stringWithFormat:@"at most %@", countPhrase];
112        default:
113            break;
114    }
115
116    assert(0 && "should never reach here");
117    return nil;
118}
119
120- (NSString *)receivedCountPhrase {
121    return [self phraseForCount:self.receivedCount];
122}
123
124#pragma mark -
125#pragma mark Debugging
126
127- (NSString *)modeString {
128    switch (self.countType) {
129        case KWCountTypeExact:
130            return @"KWCountTypeExact";
131        case KWCountTypeAtLeast:
132            return @"KWCountTypeAtLeast";
133        case KWCountTypeAtMost:
134            return @"KWCountTypeAtMost";
135        default:
136            break;
137    }
138
139    assert(0 && "should never reach here");
140    return nil;
141}
142
143- (NSString *)description {
144    return [NSString stringWithFormat:@"messagePattern: %@\nmode: %@\ncount: %d\nreceiveCount: %d",
145                                      self.messagePattern,
146                                      self.modeString,
147                                      (int)self.count,
148                                      (int)self.receivedCount];
149}
150
151@end