133 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
| //  OCHamcrest by Jon Reid, https://qualitycoding.org/
 | |
| //  Copyright 2019 hamcrest.org. See LICENSE.txt
 | |
| 
 | |
| #import "HCIsDictionaryContainingEntries.h"
 | |
| 
 | |
| #import "HCWrapInMatcher.h"
 | |
| 
 | |
| 
 | |
| @interface HCIsDictionaryContainingEntries ()
 | |
| @property (nonatomic, copy, readonly) NSArray *keys;
 | |
| @property (nonatomic, copy, readonly) NSArray<id <HCMatcher>> *valueMatchers;
 | |
| @end
 | |
| 
 | |
| @implementation HCIsDictionaryContainingEntries
 | |
| 
 | |
| - (instancetype)initWithKeys:(NSArray *)keys
 | |
|                valueMatchers:(NSArray<id <HCMatcher>> *)valueMatchers
 | |
| {
 | |
|     self = [super init];
 | |
|     if (self)
 | |
|     {
 | |
|         _keys = [keys copy];
 | |
|         _valueMatchers = [valueMatchers copy];
 | |
|     }
 | |
|     return self;
 | |
| }
 | |
| 
 | |
| - (BOOL)matches:(id)dict describingMismatchTo:(id <HCDescription>)mismatchDescription
 | |
| {
 | |
|     if (![dict isKindOfClass:[NSDictionary class]])
 | |
|     {
 | |
|         [[mismatchDescription appendText:@"was non-dictionary "] appendDescriptionOf:dict];
 | |
|         return NO;
 | |
|     }
 | |
| 
 | |
|     NSUInteger count = self.keys.count;
 | |
|     for (NSUInteger index = 0; index < count; ++index)
 | |
|     {
 | |
|         id key = self.keys[index];
 | |
|         if (dict[key] == nil)
 | |
|         {
 | |
|             [[[[mismatchDescription appendText:@"no "]
 | |
|                                     appendDescriptionOf:key]
 | |
|                                     appendText:@" key in "]
 | |
|                                     appendDescriptionOf:dict];
 | |
|             return NO;
 | |
|         }
 | |
| 
 | |
|         id valueMatcher = self.valueMatchers[index];
 | |
|         id actualValue = dict[key];
 | |
| 
 | |
|         if (![valueMatcher matches:actualValue])
 | |
|         {
 | |
|             [[[[mismatchDescription appendText:@"value for "]
 | |
|                                     appendDescriptionOf:key]
 | |
|                                     appendText:@" was "]
 | |
|                                     appendDescriptionOf:actualValue];
 | |
|             return NO;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return YES;
 | |
| }
 | |
| 
 | |
| - (void)describeKeyValueAtIndex:(NSUInteger)index to:(id <HCDescription>)description
 | |
| {
 | |
|     [[[[description appendDescriptionOf:self.keys[index]]
 | |
|                     appendText:@" = "]
 | |
|                     appendDescriptionOf:self.valueMatchers[index]]
 | |
|                     appendText:@"; "];
 | |
| }
 | |
| 
 | |
| - (void)describeTo:(id <HCDescription>)description
 | |
| {
 | |
|     [description appendText:@"a dictionary containing { "];
 | |
|     NSUInteger count = [self.keys count];
 | |
|     NSUInteger index = 0;
 | |
|     for (; index < count - 1; ++index)
 | |
|         [self describeKeyValueAtIndex:index to:description];
 | |
|     [self describeKeyValueAtIndex:index to:description];
 | |
|     [description appendText:@"}"];
 | |
| }
 | |
| 
 | |
| @end
 | |
| 
 | |
| 
 | |
| static void requirePairedObject(id obj)
 | |
| {
 | |
|     if (obj == nil)
 | |
|     {
 | |
|         @throw [NSException exceptionWithName:@"NilObject"
 | |
|                                        reason:@"HC_hasEntries keys and value matchers must be paired"
 | |
|                                      userInfo:nil];
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| id HC_hasEntriesIn(NSDictionary *valueMatchersForKeys)
 | |
| {
 | |
|     NSArray *keys = valueMatchersForKeys.allKeys;
 | |
|     NSMutableArray<id <HCMatcher>> *valueMatchers = [[NSMutableArray alloc] init];
 | |
|     for (id key in keys)
 | |
|         [valueMatchers addObject:HCWrapInMatcher(valueMatchersForKeys[key])];
 | |
| 
 | |
|     return [[HCIsDictionaryContainingEntries alloc] initWithKeys:keys
 | |
|                                                    valueMatchers:valueMatchers];
 | |
| }
 | |
| 
 | |
| id HC_hasEntries(id keysAndValueMatchers, ...)
 | |
| {
 | |
|     va_list args;
 | |
|     va_start(args, keysAndValueMatchers);
 | |
| 
 | |
|     id key = keysAndValueMatchers;
 | |
|     id valueMatcher = va_arg(args, id);
 | |
|     requirePairedObject(valueMatcher);
 | |
|     NSMutableArray *keys = [NSMutableArray arrayWithObject:key];
 | |
|     NSMutableArray<id <HCMatcher>> *valueMatchers = [NSMutableArray arrayWithObject:HCWrapInMatcher(valueMatcher)];
 | |
| 
 | |
|     key = va_arg(args, id);
 | |
|     while (key != nil)
 | |
|     {
 | |
|         [keys addObject:key];
 | |
|         valueMatcher = va_arg(args, id);
 | |
|         requirePairedObject(valueMatcher);
 | |
|         [valueMatchers addObject:HCWrapInMatcher(valueMatcher)];
 | |
|         key = va_arg(args, id);
 | |
|     }
 | |
| 
 | |
|     return [[HCIsDictionaryContainingEntries alloc] initWithKeys:keys
 | |
|                                                    valueMatchers:valueMatchers];
 | |
| }
 |