summaryrefslogtreecommitdiff
path: root/vendor/bandit/specs/matchers/throw_exception.cpp
blob: c7531d5fe65ef2c047ac79fc22761aaed66ea454 (plain)
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
#include <specs/specs.h>

using namespace bandit::Matchers;

SPEC_BEGIN(Matchers::ThrowException)

describe("throw_exception", []{
    describe("when no exception is specified", [&]{
	std::exception exception;

	std::function<void()> exception_block = [&]{ throw exception; };

        describe("when the block throws an exception", [&]{
	    it("must pass a positive match", [&]{
		exception_block must throw_exception;
	    });

	    it("must reject a negative match", [&]{
		AssertThrows(MatcherException, [&]{ exception_block must_not throw_exception; }());
	    });
        });

        describe("when the block does not throw an exception", [&]{
	    std::function<void()> quiet_block = [&]{};

	    it("must pass a negative match", [&]{
		quiet_block must_not throw_exception;
	    });

	    it("must reject a positive match", [&]{
		AssertThrows(std::exception, [&]{ quiet_block must throw_exception; }());
	    });
        });
    });

    describe("with an exception class specified", [&]{
	std::logic_error expected_exception("logic_error");

        describe("when the block throws the expected exception", [&]{
	    std::function<void()> exception_block = [&]{ throw expected_exception; };

	    it("must pass a positive match", [&]{
		exception_block must throw_exception.operator()<decltype(expected_exception)>();
	    });

	    it("must reject a negative match", [&]{
		AssertThrows(std::exception, [&]{ exception_block must_not throw_exception.operator()<decltype(expected_exception)>(); }());
	    });
        });

	// TODO: Because C++ lacks reflection, there's no way to implement
	//  subclass-checking. I'm leaving these tests here for when the
	//  language has evolved sufficiently.
        xdescribe("when the block throws a sublass of the specified exception", [&]{
	    std::function<void()> subclass_block = [&]{ throw std::invalid_argument("invalid argument"); };

            describe("when subclasses are expected", [&]{
		it("must pass a positive match", [&]{
		    subclass_block must throw_exception.operator()<std::logic_error>().or_subclass();
		});

		it("must reject a negative match", [&]{
		    AssertThrows(std::exception, [&]{ subclass_block must_not throw_exception.operator()<std::logic_error>().or_subclass(); }());
		});
            });

            describe("when subclasses are not expected", [&]{
		it("must pass a negative match", [&]{
		    subclass_block must_not throw_exception.operator()<std::logic_error>();
		});

		it("must reject a positive match", [&]{
		    AssertThrows(std::exception, [&]{ subclass_block must throw_exception.operator()<std::logic_error>(); }());
		});
            });
        });

        describe("when the block throws an unrelated exception", [&]{
	    std::function<void()> unrelated_block = [&]{ throw std::range_error("range error"); };

	    it("must pass a negative match", [&]{
		unrelated_block must_not throw_exception.operator()<decltype(expected_exception)>();
	    });

	    it("must reject a positive match", [&]{
		AssertThrows(std::exception, [&]{ unrelated_block must throw_exception.operator()<decltype(expected_exception)>(); }());
	    });
        });

        describe("when the block does not throw an exception", [&]{
	    std::function<void()> quiet_block = [&]{};

	    it("must pass a negative match", [&]{
		quiet_block must_not throw_exception.operator()<decltype(expected_exception)>();
	    });

	    it("must reject a positive match", [&]{
		AssertThrows(std::exception, [&]{ quiet_block must throw_exception.operator()<decltype(expected_exception)>(); }());
	    });
        });
    });
});

SPEC_END