-
Notifications
You must be signed in to change notification settings - Fork 0
/
DogVerifier.m
227 lines (178 loc) · 8.28 KB
/
DogVerifier.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#import "DogVerifier.h"
#import "DogEvent.h"
@interface DogVerifier()
- (void)incrementActionsReceived:(NSString *)actionName;
- (void)assertActionsReceivedFor:(NSString *)actionName is:(int)numTimesExpected;
- (int)numActionsReceivedFor:(NSString *)actionName;
- (void)assertTotalActionsReceived:(int)numTimesExpected;
@end
@implementation DogVerifier
@synthesize dog, actionTracker, totalActionsReceived;
#pragma mark -
#pragma mark Private Methods
- (int)numActionsReceivedFor:(NSString *)actionName {
if ([self.actionTracker objectForKey:actionName] != nil) {
return [[self.actionTracker objectForKey:actionName] intValue];
}
return 0;
}
- (void)incrementActionsReceived:(NSString *)actionName {
// get the existing number of times this action has been called, increment it, and set new value
NSNumber *numTimesActionCalled = [NSNumber numberWithInt:1];
if ([self.actionTracker objectForKey:actionName] != nil) {
int prevNumTimesActionCalled = [[self.actionTracker objectForKey:actionName] intValue];
prevNumTimesActionCalled += 1;
numTimesActionCalled = [NSNumber numberWithInt:prevNumTimesActionCalled];
}
[self.actionTracker setValue:numTimesActionCalled forKey:actionName];
self.totalActionsReceived += 1;
}
- (void)assertActionsReceivedFor:(NSString *)actionName is:(int)numTimesExpected {
if ([self.actionTracker objectForKey:actionName] != nil) {
int numTimesActionCalled = [[self.actionTracker objectForKey:actionName] intValue];
if (numTimesActionCalled != numTimesExpected) {
NSLog(@"assertActionsReceivedFor ASSERTION FAILED");
exit(1);
}
}
else {
if (numTimesExpected != 0) {
NSLog(@"assertActionsReceivedFor ASSERTION FAILED");
exit(1);
}
}
}
- (void)assertTotalActionsReceived:(int)numTimesExpected {
if (self.totalActionsReceived != numTimesExpected) {
NSLog(@"assertTotalActionsReceived ASSERTION FAILED");
exit(1);
}
}
#pragma mark -
#pragma mark Public Methods
- (BOOL)verify {
// local vars..
int curNumTimesPlayed, curNumTimesBarked, curNumTimesLayedDown, curNumTimesWhimpered, curNumTimesYawn = 0;
int curNumTimesBackflipped, curNumTimesBite, curNumTimesGetUp, curNumTimesVomit, curNumTimesBurp = 0;
// reset the actiontracker
self.actionTracker = [[NSMutableDictionary alloc] init];
// do initial transition (by default the dog should go into the happy / playful state)
[self.dog executeInitialTransition];
// verify dog is in happy / playful state by throwing it a ball and making sure that
// it plays with it.
DogEvent *evt = [[DogEvent alloc] init];
evt.signal = THROW_BALL_SIG;
curNumTimesPlayed = [self numActionsReceivedFor:@"play"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"play" is:(curNumTimesPlayed+1)]; // did the dog play?
// lets kick the dog, but since he's playing, he will just bark
evt.signal = KICK_SIG; // recycle event, too much trouble to create a new one..
curNumTimesBarked = [self numActionsReceivedFor:@"bark"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"bark" is:(curNumTimesBarked+1)];
// lets give the dog a burrito, which will make him tired
evt.signal = GIVE_BURRITO_SIG;
curNumTimesLayedDown = [self numActionsReceivedFor:@"lay_down"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"lay_down" is:(curNumTimesLayedDown+1)];
// lets throw the dog a ball, but since he's tired he will do nothing
evt.signal = THROW_BALL_SIG;
int curNumActionsRecevied = self.totalActionsReceived;
[self.dog dispatch:evt];
[self assertTotalActionsReceived:curNumActionsRecevied];
// now lets kick him again, but this time since he's tired, instead of barking he will whimper and go into unhappy state
evt.signal = KICK_SIG;
curNumTimesWhimpered = [self numActionsReceivedFor:@"whimper"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"whimper" is:curNumTimesWhimpered+1];
// lets throw the dog a ball, but since he's unhappy, he will just wimper
evt.signal = THROW_BALL_SIG;
curNumTimesWhimpered = [self numActionsReceivedFor:@"whimper"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"whimper" is:curNumTimesWhimpered+1];
// ok we had a really bad day and got yelled at by our boss for being THREE WEEKS LATE. lets
// take it out on the dog and kick him again. he will wimper again and go into hurt state
evt.signal = KICK_SIG;
curNumTimesWhimpered = [self numActionsReceivedFor:@"whimper"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"whimper" is:curNumTimesWhimpered+1];
// try to give him a burrito, he will look up, ignore it, and go back into the hurt state. upon
// temporarily leaving the hurt state, he will whimper
evt.signal = GIVE_BURRITO_SIG;
curNumTimesWhimpered = [self numActionsReceivedFor:@"whimper"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"whimper" is:(curNumTimesWhimpered+1)];
// lets pet him, which will make him go into the happy+playful state, and whenever he enters the happy state he barks
// and whenever he enters playful state he gets up. also when he leaves the hurt state, he will wimper to signify
// that he's still unhappy
evt.signal = PET_SIG;
curNumTimesGetUp = [self numActionsReceivedFor:@"get_up"];
curNumTimesBarked = [self numActionsReceivedFor:@"bark"];
curNumTimesWhimpered = [self numActionsReceivedFor:@"whimper"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"whimper" is:(curNumTimesWhimpered+1)];
[self assertActionsReceivedFor:@"get_up" is:curNumTimesGetUp+1];
[self assertActionsReceivedFor:@"bark" is:(curNumTimesBarked+1)];
// lets give him some whiskey! this will make him go into the happy/wasted state. he doesn't do anything upon entering this state
evt.signal = GIVE_WHISKEY_SIG;
[self.dog dispatch:evt];
// now lets throw him a ball, OMG he does a backflip!
evt.signal = THROW_BALL_SIG;
curNumTimesBackflipped = [self numActionsReceivedFor:@"backflip"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"backflip" is:curNumTimesBackflipped+1];
// lets give him some more whiskey. he vomits and goes into the unhappy/sick state
evt.signal = GIVE_WHISKEY_SIG;
curNumTimesVomit = [self numActionsReceivedFor:@"vomit"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"vomit" is:curNumTimesVomit+1];
// lets give him a burrito.. he will just whimper since he's unhappy/sick
evt.signal = GIVE_BURRITO_SIG;
curNumTimesWhimpered = [self numActionsReceivedFor:@"whimper"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"whimper" is:curNumTimesWhimpered+1];
// ok we get frustrated, lets kick him. OUCH! He bites
evt.signal = KICK_SIG;
curNumTimesBite = [self numActionsReceivedFor:@"bite"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"bite" is:curNumTimesBite+1];
// lets throw him a bone, he should burp as he leaves the unhappy/sick state, and yawns as
// he enters the happy/tired state. oh he also always barks as he enteres the happy state.
evt.signal = THROW_BONE_SIG;
curNumTimesYawn = [self numActionsReceivedFor:@"yawn"];
curNumTimesBurp = [self numActionsReceivedFor:@"burp"];
curNumTimesBarked = [self numActionsReceivedFor:@"bark"];
[self.dog dispatch:evt];
[self assertActionsReceivedFor:@"burp" is:curNumTimesBurp+1];
[self assertActionsReceivedFor:@"yawn" is:curNumTimesYawn+1];
[self assertActionsReceivedFor:@"bark" is:(curNumTimesBarked+1)];
[evt release];
return TRUE;
}
#pragma mark -
#pragma mark DogObserver
-(void)play { [self incrementActionsReceived:@"play"]; }
-(void)bark { [self incrementActionsReceived:@"bark"]; }
-(void)whimper { [self incrementActionsReceived:@"whimper"]; }
-(void)vomit { [self incrementActionsReceived:@"vomit"]; }
-(void)lay_down { [self incrementActionsReceived:@"lay_down"]; }
-(void)get_up { [self incrementActionsReceived:@"get_up"]; }
-(void)jump { [self incrementActionsReceived:@"jump"]; }
-(void)backflip { [self incrementActionsReceived:@"backflip"]; }
-(void)burp { [self incrementActionsReceived:@"burp"]; }
-(void)bite { [self incrementActionsReceived:@"bite"]; }
-(void)yawn { [self incrementActionsReceived:@"yawn"]; }
#pragma mark -
#pragma mark Accessors
- (void)setDog:(DogStateMachine *)theDog {
dog = theDog;
dog.delegate = self;
}
#pragma mark -
#pragma mark Object Lifecycle
- (void)dealloc {
self.dog = nil;
self.actionTracker = nil;
[super dealloc];
}
@end