main
1//
2// Licensed under the terms in License.txt
3//
4// Copyright 2010 Allen Ding. All rights reserved.
5//
6
7#import "KWBeWithinMatcher.h"
8#import "KWFormatter.h"
9#import "KWObjCUtilities.h"
10#import "KWValue.h"
11
12@interface KWBeWithinMatcher()
13
14#pragma mark -
15#pragma mark Properties
16
17@property (nonatomic, readwrite, retain) id distance;
18@property (nonatomic, readwrite, retain) id otherValue;
19
20@end
21
22@implementation KWBeWithinMatcher
23
24#pragma mark -
25#pragma mark Initializing
26
27- (void)dealloc {
28 [distance release];
29 [otherValue release];
30 [super dealloc];
31}
32
33#pragma mark -
34#pragma mark Properties
35
36@synthesize distance;
37@synthesize otherValue;
38
39#pragma mark -
40#pragma mark Getting Matcher Strings
41
42+ (NSArray *)matcherStrings {
43 return @[@"beWithin:of:", @"equal:withDelta:"];
44}
45
46#pragma mark -
47#pragma mark Matching
48
49// Evaluation is done by getting the underlying values as the widest data
50// types available.
51
52- (BOOL)evaluateForFloatingPoint {
53 double firstValue = [self.subject doubleValue];
54 double secondValue = [self.otherValue doubleValue];
55 double theDistance = [self.distance doubleValue];
56 double absoluteDifference = firstValue > secondValue ? firstValue - secondValue : secondValue - firstValue;
57 return absoluteDifference <= theDistance;
58}
59
60- (BOOL)evaluateForUnsignedIntegral {
61 unsigned long long firstValue = [self.subject unsignedLongLongValue];
62 unsigned long long secondValue = [self.otherValue unsignedLongLongValue];
63 unsigned long long theDistance = [self.distance unsignedLongLongValue];
64 unsigned long long absoluteDifference = firstValue > secondValue ? firstValue - secondValue : secondValue - firstValue;
65 return absoluteDifference <= theDistance;
66}
67
68- (BOOL)evaluateForSignedIntegral {
69 long long firstValue = [self.subject longLongValue];
70 long long secondValue = [self.otherValue longLongValue];
71 long long theDistance = [self.distance longLongValue];
72 long long absoluteDifference = firstValue > secondValue ? firstValue - secondValue : secondValue - firstValue;
73 return absoluteDifference <= theDistance;
74}
75
76- (BOOL)evaluate {
77 const char *objCType = [self.subject objCType];
78
79 if (KWObjCTypeIsFloatingPoint(objCType))
80 return [self evaluateForFloatingPoint];
81 else if (KWObjCTypeIsUnsignedIntegral(objCType))
82 return [self evaluateForUnsignedIntegral];
83 else
84 return [self evaluateForSignedIntegral];
85}
86
87#pragma mark -
88#pragma mark Getting Failure Messages
89
90- (NSString *)failureMessageForShould {
91 return [NSString stringWithFormat:@"expected subject to be within %@ of %@, got %@",
92 [KWFormatter formatObject:self.distance],
93 [KWFormatter formatObject:self.otherValue],
94 [KWFormatter formatObject:self.subject]];
95}
96
97- (NSString *)description
98{
99 return [NSString stringWithFormat:@"be within %@ of %@", self.distance, self.otherValue];
100}
101
102#pragma mark -
103#pragma mark Configuring Matchers
104
105- (void)beWithin:(id)aDistance of:(id)aValue {
106 self.distance = aDistance;
107 self.otherValue = aValue;
108}
109
110- (void)equal:(double)aValue withDelta:(double)aDelta {
111 [self beWithin:[KWValue valueWithDouble:aDelta] of:[KWValue valueWithDouble:aValue]];
112}
113
114@end