Skip to content
Browse files

It's done, I think…

  • Loading branch information...
1 parent 2307988 commit 111731f054b5772e8249f3a14aeb7c3fbc331cc0 Jim Dovey committed Jul 19, 2011
View
68 AQAppStateMachine/AQAppStateMachine.h
@@ -83,15 +83,15 @@
/**
Run a notification block when any bit in a range is modified.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param block The block to run when a modification occurs.
*/
- (void) notifyForChangesToStateBitsInRange: (NSRange) range
usingBlock: (void (^)(void)) block;
/**
Run a notification block when any bit within a masked range is modified.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param mask A mask showing which bits within the range should be monitored.
@param block The block to run when a modification occurs.
*/
@@ -101,7 +101,7 @@
/**
Run a notification block when any bit within a masked eight-byte range is modified.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param mask A mask showing which bits within the range should be monitored.
@param block The block to run when a modification occurs.
*/
@@ -111,7 +111,7 @@
/**
Run a notification block when any bit within a masked range is modified.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param mask A bitfield mask showing which bits within the range should be monitored.
@param block The block to run when a modification occurs.
*/
@@ -121,27 +121,27 @@
/**
Run a notification block when the bits in a given range exactly match a given value.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param value The value against which to compare the range's bits.
@param block The block to run when a modification occurs.
*/
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
toIntegerValue: (NSUInteger) value
- block: (void (^)(void)) block;
+ usingBlock: (void (^)(void)) block;
/**
Run a notification block when the bits in a given range exactly match a given 64-bit value.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param value The value against which to compare the range's bits.
@param block The block to run when a modification occurs.
*/
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
to64BitValue: (UInt64) value
- block: (void (^)(void)) block;
+ usingBlock: (void (^)(void)) block;
/**
Run a notification block when the bits in a given range exactly match a given bitfield value.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param value The value against which to compare the range's bits.
@param block The block to run when a modification occurs.
*/
@@ -151,39 +151,39 @@
/**
Run a notification block when the bits in a given range exactly match a given masked value.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param mask A mask denoting which bits within the range should be compared.
@param value The value against which to compare the range's bits.
@param block The block to run when a modification occurs.
*/
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
maskedWith: (NSUInteger) mask
toIntegerValue: (NSUInteger) value
- block: (void (^)(void)) block;
+ usingBlock: (void (^)(void)) block;
/**
Run a notification block when the bits in a given range exactly match a given masked 64-bit value.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param mask A mask denoting which bits within the range should be compared.
@param value The value against which to compare the range's bits.
@param block The block to run when a modification occurs.
*/
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
maskedWith: (UInt64) mask
to64BitValue: (UInt64) value
- block: (void (^)(void)) block;
+ usingBlock: (void (^)(void)) block;
/**
Run a notification block when the bits in a given range exactly match a given masked bitfield.
- @param index The range of bits to watch for changes.
+ @param range The range of bits to watch for changes.
@param mask A mask bitfield denoting which bits within the range should be compared.
@param value The bitfield against which to compare the range's bits.
@param block The block to run when a modification occurs.
*/
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
maskedWith: (AQBitfield *) mask
toValue: (AQBitfield *) value
- block: (void (^)(void)) block;
+ usingBlock: (void (^)(void)) block;
@end
@@ -354,7 +354,7 @@
@param block A block to run upon any changes.
*/
- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
- toUInt64: (NSUInteger) value
+ toUInt64: (UInt64) value
usingBlock: (void (^)(void)) block;
/**
@@ -367,6 +367,42 @@
toBits: (AQBitfield *) bits
usingBlock: (void (^)(void)) block;
+/**
+ Request notification whenever the masked content of a named enumeration matches a 32-bit scalar value.
+ @param name The name of the enumeration to monitor.
+ @param mask A mask defining which bits to compare.
+ @param value The value against which to compare the enumeration.
+ @param block A block to run upon any changes.
+ */
+- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
+ maskedWith: (NSUInteger) mask
+ toInteger: (NSUInteger) value
+ usingBlock: (void (^)(void)) block;
+
+/**
+ Request notification whenever the masked content of a named enumeration matches a 64-bit scalar value.
+ @param name The name of the enumeration to monitor.
+ @param mask A mask defining which bits to compare.
+ @param value The value against which to compare the enumeration.
+ @param block A block to run upon any changes.
+ */
+- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
+ maskedWith: (UInt64) mask
+ toUInt64: (UInt64) value
+ usingBlock: (void (^)(void)) block;
+
+/**
+ Request notification whenever the masked content of a named enumeration matches a bitfield.
+ @param name The name of the enumeration to monitor.
+ @param mask A mask defining which bits to compare.
+ @param bits The bitfield against which to compare the enumeration.
+ @param block A block to run upon any changes.
+ */
+- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
+ maskedWith: (AQBitfield *) mask
+ toBits: (AQBitfield *) bits
+ usingBlock: (void (^)(void)) block;
+
@end
/**
View
112 AQAppStateMachine/AQAppStateMachine.m
@@ -184,7 +184,7 @@ - (void) notifyForChangesToStateBitsInRange: (NSRange) range
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
toIntegerValue: (NSUInteger) value
- block: (void (^)(void)) block
+ usingBlock: (void (^)(void)) block
{
AQStateMaskedEqualityMatchingDescriptor * desc = [[AQStateMaskedEqualityMatchingDescriptor alloc] initWith32BitValue: value forRange: range];
[self _notifyForChangesToStatesMatchingDescriptor: desc usingBlock: block];
@@ -195,7 +195,7 @@ - (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
to64BitValue: (UInt64) value
- block: (void (^)(void)) block
+ usingBlock: (void (^)(void)) block
{
AQStateMaskedEqualityMatchingDescriptor * desc = [[AQStateMaskedEqualityMatchingDescriptor alloc] initWith64BitValue: value forRange: range];
[self _notifyForChangesToStatesMatchingDescriptor: desc usingBlock: block];
@@ -218,7 +218,7 @@ - (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
maskedWith: (NSUInteger) mask
toIntegerValue: (NSUInteger) value
- block: (void (^)(void)) block
+ usingBlock: (void (^)(void)) block
{
AQStateMaskedEqualityMatchingDescriptor * desc = [[AQStateMaskedEqualityMatchingDescriptor alloc] initWith32BitValue: value forRange: range matchingMask: mask];
[self _notifyForChangesToStatesMatchingDescriptor: desc usingBlock: block];
@@ -230,7 +230,7 @@ - (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
maskedWith: (UInt64) mask
to64BitValue: (UInt64) value
- block: (void (^)(void)) block
+ usingBlock: (void (^)(void)) block
{
AQStateMaskedEqualityMatchingDescriptor * desc = [[AQStateMaskedEqualityMatchingDescriptor alloc] initWith64BitValue: value forRange: range matchingMask: mask];
[self _notifyForChangesToStatesMatchingDescriptor: desc usingBlock: block];
@@ -242,7 +242,7 @@ - (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
- (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
maskedWith: (AQBitfield *) mask
toValue: (AQBitfield *) value
- block: (void (^)(void)) block
+ usingBlock: (void (^)(void)) block
{
AQStateMaskedEqualityMatchingDescriptor * desc = [[AQStateMaskedEqualityMatchingDescriptor alloc] initWithRange: range matchingValue: value withMask: mask];
[self _notifyForChangesToStatesMatchingDescriptor: desc usingBlock: block];
@@ -255,6 +255,7 @@ - (void) notifyForEqualityOfStateBitsInRange: (NSRange) range
@implementation AQAppStateMachine (NamedStateEnumerations)
+#if 0
static inline NSUInteger HighestOneBit32(NSUInteger x)
{
x |= x >> 1;
@@ -275,6 +276,29 @@ static inline NSUInteger HighestOneBit64(UInt64 x)
x |= x >> 32;
return ( (NSUInteger)(x & ~(x >> 1)) );
}
+#else
+static inline NSUInteger HighestOneBit32(NSUInteger x)
+{
+ NSUInteger i = 0;
+ for ( i = 0; i < 32; i++, x >>= 1 )
+ {
+ if ( x == 0 )
+ break;
+ }
+ return ( i );
+}
+
+static inline NSUInteger HighestOneBit64(UInt64 x)
+{
+ NSUInteger i = 0;
+ for ( i = 0; i < 64; i++, x >>= 1 )
+ {
+ if ( x == 0 )
+ break;
+ }
+ return ( i );
+}
+#endif
- (void) addStateMachineValuesFromZeroTo: (NSUInteger) maxValue withName: (NSString *) name
{
@@ -403,29 +427,65 @@ - (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
if ( range == nil )
return; // nonexistent named range
+ [self notifyForEqualityOfStateBitsInRange: range.range toIntegerValue: value usingBlock: block];
+}
+
+- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
+ toUInt64: (UInt64) value
+ usingBlock: (void (^)(void)) block
+{
+ AQRange * range = [_namedRanges objectForKey: name];
+ if ( range == nil )
+ return; // nonexistent named range
+ [self notifyForEqualityOfStateBitsInRange: range.range to64BitValue: value usingBlock: block];
}
- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
- toUInt64: (NSUInteger) value
+ toBits: (AQBitfield *) bits
usingBlock: (void (^)(void)) block
{
AQRange * range = [_namedRanges objectForKey: name];
if ( range == nil )
return; // nonexistent named range
+ [self notifyForEqualityOfStateBitsInRange: range.range toValue: bits usingBlock: block];
+}
+
+- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
+ maskedWith: (NSUInteger) mask
+ toInteger: (NSUInteger) value
+ usingBlock: (void (^)(void)) block
+{
+ AQRange * range = [_namedRanges objectForKey: name];
+ if ( range == nil )
+ return; // nonexistent named range
+ [self notifyForEqualityOfStateBitsInRange: range.range maskedWith: mask toIntegerValue: value usingBlock: block];
}
- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
- toBits: (AQBitfield *) bits
+ maskedWith: (UInt64) mask
+ toUInt64: (UInt64) value
usingBlock: (void (^)(void)) block
{
AQRange * range = [_namedRanges objectForKey: name];
if ( range == nil )
return; // nonexistent named range
+ [self notifyForEqualityOfStateBitsInRange: range.range maskedWith: mask to64BitValue: value usingBlock: block];
+}
+
+- (void) notifyEqualityOfStateMachineValuesWithName: (NSString *) name
+ maskedWith: (AQBitfield *) mask
+ toBits: (AQBitfield *) bits
+ usingBlock: (void (^)(void)) block
+{
+ AQRange * range = [_namedRanges objectForKey: name];
+ if ( range == nil )
+ return; // nonexistent named range
+ [self notifyForEqualityOfStateBitsInRange: range.range maskedWith: mask toValue: bits usingBlock: block];
}
- (BOOL) bitIsSetAtIndex: (NSUInteger) index forName: (NSString *) name
@@ -497,7 +557,19 @@ - (void) notifyChangesToStateMachineValuesWithNames: (NSArray *) names
NSParameterAssert(block != nil);
NSMutableArray * ranges = [NSMutableArray new];
- [names enumerateObjectsUsingBlock: ^(__strong id obj, NSUInteger idx, BOOL *stop){[ranges addObject: obj];}];
+ [names enumerateObjectsUsingBlock: ^(__strong id obj, NSUInteger idx, BOOL *stop) {
+ NSRange range = [self underlyingBitfieldRangeForName: obj];
+ if ( range.location == NSNotFound )
+ {
+ NSAssert(NO, @"No range registered for name '%@'", obj);
+ }
+
+ AQRange * r = [[AQRange alloc] initWithRange: range];
+ [ranges addObject: r];
+#if !USING_ARC
+ [r release];
+#endif
+ }];
NSMutableArray * bitmasks = [NSMutableArray new];
[masks enumerateObjectsUsingBlock: ^(__strong id obj, NSUInteger idx, BOOL *stop) {
@@ -509,23 +581,23 @@ - (void) notifyChangesToStateMachineValuesWithNames: (NSArray *) names
{
AQBitfield * field = [AQBitfield new];
UInt64 bits = [obj unsignedLongLongValue];
- for ( NSUInteger i = 0; i > 0; i++, bits >>= 1 )
+ for ( NSUInteger i = 0; i < 64; i++, bits >>= 1 )
{
if ( (bits & 1) == 1 )
[field setBit: 1 atIndex: i];
}
[bitmasks addObject: field];
}
- else
+ else if ( obj != [NSNull null] )
{
// throw an exception, but only on debug builds
NSAssert(NO, @"Invalid object type in masks array: %@", NSStringFromClass([obj class]));
}
}];
AQStateMaskMatchingDescriptor * desc = [[AQStateMaskMatchingDescriptor alloc] initWithRanges: ranges
- matchingMasks: bitmasks];
+ matchingMasks: bitmasks];
[self _notifyForChangesToStatesMatchingDescriptor: desc usingBlock: block];
#if !USING_ARC
[ranges release];
@@ -543,7 +615,19 @@ - (void) notifyEqualityOfStateMachineValuesWithNames: (NSArray *) names
NSParameterAssert(block != nil);
NSMutableArray * ranges = [NSMutableArray new];
- [names enumerateObjectsUsingBlock: ^(__strong id obj, NSUInteger idx, BOOL *stop){[ranges addObject: obj];}];
+ [names enumerateObjectsUsingBlock: ^(__strong id obj, NSUInteger idx, BOOL *stop) {
+ NSRange range = [self underlyingBitfieldRangeForName: obj];
+ if ( range.location == NSNotFound )
+ {
+ NSAssert(NO, @"No range registered for name '%@'", obj);
+ }
+
+ AQRange * r = [[AQRange alloc] initWithRange: range];
+ [ranges addObject: r];
+#if !USING_ARC
+ [r release];
+#endif
+ }];
NSMutableArray * bitmasks = [NSMutableArray new];
[masks enumerateObjectsUsingBlock: ^(__strong id obj, NSUInteger idx, BOOL *stop) {
@@ -555,15 +639,15 @@ - (void) notifyEqualityOfStateMachineValuesWithNames: (NSArray *) names
{
AQBitfield * field = [AQBitfield new];
UInt64 bits = [obj unsignedLongLongValue];
- for ( NSUInteger i = 0; i > 0; i++, bits >>= 1 )
+ for ( NSUInteger i = 0; bits > 0; i++, bits >>= 1 )
{
if ( (bits & 1) == 1 )
[field setBit: 1 atIndex: i];
}
[bitmasks addObject: field];
}
- else
+ else if ( obj != [NSNull null] )
{
// throw an exception, but only on debug builds
NSAssert(NO, @"Invalid object type in masks array: %@", NSStringFromClass([obj class]));
View
4 AQAppStateMachine/AQStateMaskedEqualityMatchingDescriptor.h
@@ -112,7 +112,7 @@
/**
Initialize a descriptor using a single range and a 32-bit value.
- @param mask A value specifying the exact bits within the range to match. Can be zero.
+ @param value A value specifying the exact bits within the range to match. Can be zero.
@param range The range to match.
@param mask A value specifying which bits to compare during the match.
@return The newly-initialized instance.
@@ -121,7 +121,7 @@
/**
Initialize a descriptor using a single range and a 64-bit mask.
- @param mask A value specifying the exact bits within the range to match. Can be zero.
+ @param value A value specifying the exact bits within the range to match. Can be zero.
@param range The range to match.
@param mask A value specifying which bits to compare during the match.
@return The newly-initialized instance.
View
10 AQAppStateMachine/AQStateMaskedEqualityMatchingDescriptor.m
@@ -76,7 +76,12 @@ - (id)initWithRanges: (NSArray *) ranges masks: (NSArray *) masks matchingValues
if ( [masks count] > idx )
mask = [masks objectAtIndex: idx];
- AQBitfield * modified = [obj copy];
+ AQBitfield * modified = nil;
+ if ( [obj isKindOfClass: [NSNumber class]] )
+ modified = [[AQBitfield alloc] initWith64BitField: [obj unsignedLongLongValue]];
+ else
+ modified = [obj copy];
+
if ( mask != nil )
[modified maskWithBits: mask];
@@ -85,6 +90,9 @@ - (id)initWithRanges: (NSArray *) ranges masks: (NSArray *) masks matchingValues
[modified shiftBitsRightBy: range.location];
[_value unionWithBitfield: modified];
+#if !USING_ARC
+ [modified release];
+#endif
}];
}
View
153 AQAppStateMachineTests/AQAppStateMachineCoreTests.m
@@ -143,7 +143,7 @@ - (void) testEnumerationChangeNotifications
- (void) testSingleBitChangeNotifications
{
__block BOOL matched = NO;
- [stateMachine notifyChangesToStateMachineValuesWithName: kSampleOneName matchingMask: kSampleOneSecond usingBlock: ^{ matched = YES; }];
+ [stateMachine notifyChangesToStateMachineValuesWithName: kSampleOneName matchingMask: 0x01 usingBlock: ^{ matched = YES; }];
[stateMachine setBitAtIndex: 0 ofEnumerationWithName: kSampleOneName];
@@ -186,4 +186,155 @@ - (void) testValueChangeNotifications
STAssertTrue(matched, @"Expected block to be called when kSampleTwoFourth was set in %@", kSampleTwoName);
}
+- (void) testEqualityNotifications
+{
+ static NSString * const kEqualityEnum = @"Equality";
+ static const NSUInteger kMatchValue = 548;
+
+ [stateMachine addStateMachineValuesFromZeroTo: USHRT_MAX withName: kEqualityEnum];
+
+ __block BOOL matched = NO;
+ [stateMachine notifyEqualityOfStateMachineValuesWithName: kEqualityEnum toInteger: 548 usingBlock: ^{ matched = YES; }];
+
+ // set that value, verify that the match is called
+ [stateMachine setValue: kMatchValue forEnumerationWithName: kEqualityEnum];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected equality notifier on %@ to fire when value was set to %lu", kEqualityEnum, (unsigned long)kMatchValue);
+
+ // set a different value, ensure it does NOT fire the notification
+ matched = NO;
+ [stateMachine setValue: kMatchValue+1 forEnumerationWithName: kEqualityEnum];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertFalse(matched, @"Expected equality notifier on %@ NOT to fire when value was set to %lu", kEqualityEnum, (unsigned long)kMatchValue);
+
+ // set it again and verify that it once more fires
+ matched = NO;
+ [stateMachine setValue: kMatchValue forEnumerationWithName: kEqualityEnum];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected equality notifier on %@ to fire when value was re-set to %lu", kEqualityEnum, (unsigned long)kMatchValue);
+}
+
+- (void) testMultipleValueChangeNotifications
+{
+ __block BOOL matched = NO;
+ NSArray * values = [NSArray arrayWithObjects: kSampleOneName, kSampleTwoName, nil];
+ NSArray * masks = [NSArray arrayWithObjects: [NSNull null], [NSNull null], nil];
+
+ [stateMachine notifyChangesToStateMachineValuesWithNames: values matchingMasks: masks usingBlock: ^{ matched = YES; }];
+
+ [stateMachine setValue: kSampleTwoThird forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when kSampleTwoThird was set in %@", kSampleTwoName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleOneSecond forEnumerationWithName: kSampleOneName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when kSampleOneSecond was set in %@", kSampleOneName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleTwoFourth forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when kSampleTwoFourth was set in %@", kSampleTwoName);
+}
+
+- (void) testMultipleValueChangeNotificationsWithMasks
+{
+ __block BOOL matched = NO;
+ NSArray * values = [NSArray arrayWithObjects: kSampleOneName, kSampleTwoName, nil];
+ NSArray * masks = [NSArray arrayWithObjects: [NSNumber numberWithInt: kSampleOneThird], [NSNumber numberWithInt: kSampleTwoThird], nil];
+
+ [stateMachine notifyChangesToStateMachineValuesWithNames: values matchingMasks: masks usingBlock: ^{ matched = YES; }];
+
+ [stateMachine setValue: kSampleTwoThird forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when kSampleTwoThird was set in %@", kSampleTwoName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleOneSecond forEnumerationWithName: kSampleOneName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when kSampleOneSecond was set in %@", kSampleOneName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleTwoFourth forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when kSampleTwoFourth was set in %@", kSampleTwoName);
+}
+
+- (void) testMultipleValueEqualityNotifications
+{
+ __block BOOL matched = NO;
+ NSArray * names = [NSArray arrayWithObjects: kSampleOneName, kSampleTwoName, nil];
+ NSArray * masks = [NSArray arrayWithObjects: [NSNull null], [NSNull null], nil];
+ NSArray * values = [NSArray arrayWithObjects: [NSNumber numberWithInt: kSampleOneSecond], [NSNumber numberWithInt: kSampleTwoSecond], nil];
+
+ // reset the state machine
+ [stateMachine setValue: 0 forEnumerationWithName: kSampleOneName];
+ [stateMachine setValue: 0 forEnumerationWithName: kSampleTwoName];
+
+ [stateMachine notifyEqualityOfStateMachineValuesWithNames: names matchingMasks: masks toValues: values usingBlock: ^{ matched = YES; }];
+
+ [stateMachine setValue: kSampleTwoSecond forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertFalse(matched, @"Expected block NOT to be called when kSampleTwoThird was set in %@", kSampleTwoName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleOneSecond forEnumerationWithName: kSampleOneName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when both kSampleOneSecond was set in %@ and kSampleTwoSecond was set in %@", kSampleOneName, kSampleTwoName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleTwoFourth forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertFalse(matched, @"Expected block to be called when kSampleTwoFourth was set in %@", kSampleTwoName);
+}
+
+- (void) testMultipleValueEqualityNotificationsWithMasks
+{
+ __block BOOL matched = NO;
+ NSArray * names = [NSArray arrayWithObjects: kSampleOneName, kSampleTwoName, nil];
+ NSArray * masks = [NSArray arrayWithObjects: [NSNumber numberWithInt: kSampleOneThird], [NSNumber numberWithInt: kSampleTwoThird], nil];
+ NSArray * values = [NSArray arrayWithObjects: [NSNumber numberWithInt: kSampleOneFourth], [NSNumber numberWithInt: kSampleTwoFourth], nil];
+
+ // reset the state machine
+ [stateMachine setValue: 0 forEnumerationWithName: kSampleOneName];
+ [stateMachine setValue: 0 forEnumerationWithName: kSampleTwoName];
+
+ [stateMachine notifyEqualityOfStateMachineValuesWithNames: names matchingMasks: masks toValues: values usingBlock: ^{ matched = YES; }];
+
+ [stateMachine setValue: kSampleTwoThird forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertFalse(matched, @"Expected block NOT to be called when only kSampleTwoThird was set in %@", kSampleTwoName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleOneSecond forEnumerationWithName: kSampleOneName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertFalse(matched, @"Expected block NOT to be called when kSampleOneSecond was set in %@", kSampleOneName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleTwoFourth forEnumerationWithName: kSampleTwoName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertFalse(matched, @"Expected block NOT to be called when kSampleTwoFourth was set in %@", kSampleTwoName);
+
+ matched = NO;
+ [stateMachine setValue: kSampleOneFourth forEnumerationWithName: kSampleOneName];
+
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.05]];
+ STAssertTrue(matched, @"Expected block to be called when both kSampleTwoFourth nad kSampleOneFourth were set", kSampleTwoName);
+}
+
@end

0 comments on commit 111731f

Please sign in to comment.
Something went wrong with that request. Please try again.