Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Implies" matcher #295

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cedar.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@
2234907F18009DAD001C8E8D /* CDRHooks.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = 2234907C18009DA6001C8E8D /* CDRHooks.h */; };
228F3FA717E3ECD10000C8AF /* CDRSpyiOSSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 228F3FA617E3ECD10000C8AF /* CDRSpyiOSSpec.mm */; };
22B6A22715B7ACF800960ADE /* InvocationMatcher.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE597B4015B0638B00EEF305 /* InvocationMatcher.h */; };
268A80C81A036D9000798659 /* Imply.h in Headers */ = {isa = PBXBuildFile; fileRef = 268A80C71A036D8400798659 /* Imply.h */; settings = {ATTRIBUTES = (Public, ); }; };
268A80C91A036D9100798659 /* Imply.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = 268A80C71A036D8400798659 /* Imply.h */; };
26F100531A0378DB00975D83 /* ImplySpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26F100511A0378CA00975D83 /* ImplySpec.mm */; };
26F100541A0378DD00975D83 /* ImplySpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26F100511A0378CA00975D83 /* ImplySpec.mm */; };
3414776E191406E700CBA385 /* ComparatorsContainerConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = AEFF375718FC452E002DA993 /* ComparatorsContainerConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; };
3414776F191406FC00CBA385 /* ComparatorsContainerConvenience.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AEFF375718FC452E002DA993 /* ComparatorsContainerConvenience.h */; };
34147770191408C900CBA385 /* AnInstanceOf.h in Headers */ = {isa = PBXBuildFile; fileRef = 34D1E67A18F7A2E6005161AD /* AnInstanceOf.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -623,6 +627,7 @@
AEEE226211DC2C8300029872 /* CDRSpecHelper.h in Copy headers to framework */,
AEC9DEF112C2CC7E0039512D /* CDRColorizedReporter.h in Copy headers to framework */,
AE18A7B813F450A700C8872C /* Base.h in Copy headers to framework */,
268A80C91A036D9100798659 /* Imply.h in Copy headers to framework */,
AE18A7B913F450A700C8872C /* BeCloseTo.h in Copy headers to framework */,
2234907F18009DAD001C8E8D /* CDRHooks.h in Copy headers to framework */,
AE02E814184ECB0F00414F19 /* ShouldSyntax.h in Copy headers to framework */,
Expand Down Expand Up @@ -693,6 +698,8 @@
1FF449B318A0C04D00AF94B0 /* CDRBufferedDefaultReporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = CDRBufferedDefaultReporter.h; sourceTree = "<group>"; };
2234907C18009DA6001C8E8D /* CDRHooks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDRHooks.h; sourceTree = "<group>"; };
228F3FA617E3ECD10000C8AF /* CDRSpyiOSSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = CDRSpyiOSSpec.mm; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
268A80C71A036D8400798659 /* Imply.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Imply.h; sourceTree = "<group>"; };
26F100511A0378CA00975D83 /* ImplySpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ImplySpec.mm; sourceTree = "<group>"; };
342F5D0A18F430DB00F38E35 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
343FAFE8190FDAEC0085AFEC /* DeallocNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeallocNotifier.h; sourceTree = "<group>"; };
343FAFE9190FDAEC0085AFEC /* DeallocNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeallocNotifier.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1724,6 +1731,7 @@
5898AEAF3FE8C683E6F23C1D /* ConformTo.h */,
AEF7300113ECC21E00786282 /* Equal.h */,
AE0721E2187518FD0031CC42 /* Exist.h */,
268A80C71A036D8400798659 /* Imply.h */,
AEB45A901496C8D800845D09 /* RaiseException.h */,
CA17998C17F89C4B00C38060 /* RespondTo.h */,
);
Expand All @@ -1748,6 +1756,7 @@
5898A53A07BC580786243CD0 /* ConformToSpec.mm */,
AEF7301913ECC4AE00786282 /* EqualSpec.mm */,
AE0721DF187513870031CC42 /* ExistSpec.mm */,
26F100511A0378CA00975D83 /* ImplySpec.mm */,
AEF7301A13ECC4AE00786282 /* MutableEqualSpec.mm */,
AEBB92601496C1F000EEBD59 /* RaiseExceptionSpec.mm */,
CA17999217F8A0EE00C38060 /* RespondToSpec.mm */,
Expand Down Expand Up @@ -1886,6 +1895,7 @@
AE4A945E1880792E008566F5 /* RejectedMethod.h in Headers */,
AEEE1FFA11DC27B800029872 /* CDRExample.h in Headers */,
AEEE1FFC11DC27B800029872 /* CDRExampleGroup.h in Headers */,
268A80C81A036D9000798659 /* Imply.h in Headers */,
969B6F96160F1FEC00C7C792 /* CDRSymbolicator.h in Headers */,
AE84F0DB145B70DD00769F85 /* ShouldSyntax.h in Headers */,
34147770191408C900CBA385 /* AnInstanceOf.h in Headers */,
Expand Down Expand Up @@ -2582,6 +2592,7 @@
AE9AA68015AB748E00617E1A /* CDRClassFakeSpec.mm in Sources */,
AE807893183C71950078C608 /* SimpleKeyValueObserver.m in Sources */,
AE9AA69715ADB99800617E1A /* CedarDoubleSharedExamples.mm in Sources */,
26F100531A0378DB00975D83 /* ImplySpec.mm in Sources */,
AE3E8F39184FEEE900633740 /* ObjectWithCollections.m in Sources */,
AE74903215B45EBA008EA127 /* CDRProtocolFakeSpec.mm in Sources */,
343FAFEA190FDAEC0085AFEC /* DeallocNotifier.m in Sources */,
Expand Down Expand Up @@ -2689,6 +2700,7 @@
1FDCD5611821D3BF00B511DB /* BeSameInstanceAs_ARCSpec.mm in Sources */,
AEF7302D13ECC4E700786282 /* BeEmptySpec.mm in Sources */,
228F3FA717E3ECD10000C8AF /* CDRSpyiOSSpec.mm in Sources */,
26F100541A0378DD00975D83 /* ImplySpec.mm in Sources */,
44B9A71F1888661100CBCA1B /* ExampleWithPublicRunDates.m in Sources */,
AE18A80B13F4640600C8872C /* ContainSpec.mm in Sources */,
AED10EBD18F46C0E00950904 /* FooSuperclass.m in Sources */,
Expand Down
58 changes: 58 additions & 0 deletions Source/Headers/Matchers/Base/Imply.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#import <Foundation/Foundation.h>
#import "Base.h"

#pragma mark - private interface
namespace Cedar { namespace Matchers { namespace Private {

template<typename T>
class Imply : public Base<> {
private:
Imply<T> & operator=(const Imply<T> &);

public:
explicit Imply(const T & expectedValue);
~Imply();
// Allow default copy ctor.

template<typename U>
bool matches(const U &) const;

protected:
virtual NSString * failure_message_end() const;

private:
const T & expectedValue_;
};

template<typename T>
Imply<T>::Imply(const T & expectedValue)
: Base<>(), expectedValue_(expectedValue) {
}

template<typename T>
Imply<T>::~Imply() {
}

template<typename T>
/*virtual*/ NSString * Imply<T>::failure_message_end() const {
NSString * expectedValueString = Stringifiers::string_for(expectedValue_);
return [NSString stringWithFormat:@"imply <%@>", expectedValueString];
}

template<typename T> template<typename U>
bool Imply<T>::matches(const U & actualValue) const {
return !!expectedValue_ || !actualValue;
}

}}}

#pragma mark - public interface
namespace Cedar { namespace Matchers {
template<typename T>
using CedarImply = Cedar::Matchers::Private::Imply<T>;

template<typename T>
CedarImply<T> imply(const T & expectedValue) {
return CedarImply<T>(expectedValue);
}
}}
1 change: 1 addition & 0 deletions Source/Headers/Matchers/CedarMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import "BeGTE.h"
#import "BeLessThan.h"
#import "BeLTE.h"
#import "Imply.h"
#import "RaiseException.h"
#import "RespondTo.h"
#import "ConformTo.h"
Expand Down
219 changes: 219 additions & 0 deletions Spec/Matchers/Base/ImplySpec.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
#if TARGET_OS_IPHONE
#import <Cedar/CDRSpecHelper.h>
#else
#import <Cedar/CDRSpecHelper.h>
#endif

extern "C" {
#import "ExpectFailureWithMessage.h"
}

using namespace Cedar::Matchers;

SPEC_BEGIN(ImplySpec)

describe(@"implies matcher", ^{
describe(@"when the values are built-in type", ^{
describe(@"which evaluates to true", ^{
describe(@"positive match", ^{
it(@"should pass", ^{
expect(YES).to(imply(YES));
});

it(@"should pass", ^{
expect(NO).to(imply(YES));
});

it(@"should pass", ^{
expect(NO).to(imply(NO));
});
});

describe(@"negative match", ^{
it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <YES> to not imply <YES>", ^{
expect(YES).to_not(imply(YES));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <NO> to not imply <YES>", ^{
expect(NO).to_not(imply(YES));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <NO> to not imply <NO>", ^{
expect(NO).to_not(imply(NO));
});
});
});
});

describe(@"which evaluates to false", ^{
describe(@"positive match", ^{
it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <YES> to imply <NO>", ^{
expect(YES).to(imply(NO));
});
});
});

describe(@"negative match", ^{
it(@"should should pass", ^{
expect(YES).to_not(imply(NO));
});
});
});
});

describe(@"when the value is an id", ^{
describe(@"which evaluates to true", ^{
describe(@"positive match", ^{
it(@"should pass", ^{
expect(@"wurble").to(imply(@"wurble"));
});

it(@"should pass", ^{
expect((id)nil).to(imply(@"wurble"));
});

it(@"should pass", ^{
expect((id)nil).to(imply((id)nil));
});
});

describe(@"negative match", ^{
it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <wurble> to not imply <wurble>", ^{
expect(@"wurble").to_not(imply(@"wurble"));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <(null)> to not imply <wurble>", ^{
expect((id)nil).to_not(imply(@"wurble"));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <(null)> to not imply <(null)>", ^{
expect((id)nil).to_not(imply((id)nil));
});
});
});
});

describe(@"which evaluates to false", ^{
describe(@"positive match", ^{
it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <wurble> to imply <(null)>", ^{
expect(@"wurble").to(imply((id)nil));
});
});
});

describe(@"negative match", ^{
it(@"should should pass", ^{
expect(@"wurble").to_not(imply((id)nil));
});
});
});
});

describe(@"when the values are mixed", ^{
describe(@"which evaluates to true", ^{
describe(@"positive match", ^{
it(@"should pass", ^{
expect(@"wurble").to(imply(YES));
});

it(@"should pass", ^{
expect((id)nil).to(imply(YES));
});

it(@"should pass", ^{
expect((id)nil).to(imply(NO));
});

it(@"should pass", ^{
expect(YES).to(imply(@"wurble"));
});

it(@"should pass", ^{
expect(NO).to(imply(@"wurble"));
});

it(@"should pass", ^{
expect(NO).to(imply((id)nil));
});
});

describe(@"negative match", ^{
it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <wurble> to not imply <YES>", ^{
expect(@"wurble").to_not(imply(YES));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <(null)> to not imply <YES>", ^{
expect((id)nil).to_not(imply(YES));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <(null)> to not imply <NO>", ^{
expect((id)nil).to_not(imply(NO));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <YES> to not imply <wurble>", ^{
expect(YES).to_not(imply(@"wurble"));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <NO> to not imply <wurble>", ^{
expect(NO).to_not(imply(@"wurble"));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <NO> to not imply <(null)>", ^{
expect(NO).to_not(imply((id)nil));
});
});
});
});

describe(@"which evaluates to false", ^{
describe(@"positive match", ^{
it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <wurble> to imply <NO>", ^{
expect(@"wurble").to(imply(NO));
});
});

it(@"should fail with a sensible failure message", ^{
expectFailureWithMessage(@"Expected <YES> to imply <(null)>", ^{
expect(YES).to(imply((id)nil));
});
});
});

describe(@"negative match", ^{
it(@"should should pass", ^{
expect(@"wurble").to_not(imply(NO));
});

it(@"should should pass", ^{
expect(YES).to_not(imply((id)nil));
});
});
});
});
});

SPEC_END