summaryrefslogtreecommitdiff
path: root/vendor/bandit/specs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/bandit/specs')
-rw-r--r--vendor/bandit/specs/before_each_after_each.spec.cpp78
-rw-r--r--vendor/bandit/specs/context.spec.cpp44
-rw-r--r--vendor/bandit/specs/describe.spec.cpp117
-rw-r--r--vendor/bandit/specs/failure_formatters/default_formatter.spec.cpp21
-rw-r--r--vendor/bandit/specs/failure_formatters/visual_studio_failure_formatter.spec.cpp22
-rw-r--r--vendor/bandit/specs/fakes/fake_context.h69
-rw-r--r--vendor/bandit/specs/fakes/fake_reporter.h78
-rw-r--r--vendor/bandit/specs/fakes/fakes.h8
-rw-r--r--vendor/bandit/specs/fakes/logging_fake.h32
-rw-r--r--vendor/bandit/specs/fuzzbox.spec.cpp77
-rw-r--r--vendor/bandit/specs/it.spec.cpp355
-rw-r--r--vendor/bandit/specs/main.cpp6
-rw-r--r--vendor/bandit/specs/matchers/be_close_to.cpp112
-rw-r--r--vendor/bandit/specs/matchers/be_empty.cpp89
-rw-r--r--vendor/bandit/specs/matchers/be_falsy.cpp85
-rw-r--r--vendor/bandit/specs/matchers/be_greater_than.cpp105
-rw-r--r--vendor/bandit/specs/matchers/be_gte.cpp120
-rw-r--r--vendor/bandit/specs/matchers/be_less_than.cpp105
-rw-r--r--vendor/bandit/specs/matchers/be_lte.cpp119
-rw-r--r--vendor/bandit/specs/matchers/be_null.cpp43
-rw-r--r--vendor/bandit/specs/matchers/be_truthy.cpp85
-rw-r--r--vendor/bandit/specs/matchers/contain.cpp156
-rw-r--r--vendor/bandit/specs/matchers/equal.cpp214
-rw-r--r--vendor/bandit/specs/matchers/throw_exception.cpp104
-rw-r--r--vendor/bandit/specs/options.spec.cpp121
-rw-r--r--vendor/bandit/specs/reporters/colorizer.spec.cpp45
-rw-r--r--vendor/bandit/specs/reporters/dots_reporter.spec.cpp202
-rw-r--r--vendor/bandit/specs/reporters/single_line_reporter.spec.cpp201
-rw-r--r--vendor/bandit/specs/reporters/xunit_reporter.spec.cpp161
-rw-r--r--vendor/bandit/specs/run.spec.cpp77
-rw-r--r--vendor/bandit/specs/run_policies/bandit_run_policy.spec.cpp250
-rw-r--r--vendor/bandit/specs/specs.h10
-rw-r--r--vendor/bandit/specs/synopsis.spec.cpp54
-rw-r--r--vendor/bandit/specs/util/argv_helper.h62
-rw-r--r--vendor/bandit/specs/util/util.h6
35 files changed, 3433 insertions, 0 deletions
diff --git a/vendor/bandit/specs/before_each_after_each.spec.cpp b/vendor/bandit/specs/before_each_after_each.spec.cpp
new file mode 100644
index 00000000..29d40574
--- /dev/null
+++ b/vendor/bandit/specs/before_each_after_each.spec.cpp
@@ -0,0 +1,78 @@
+#include <specs/specs.h>
+
+namespace bf = bandit::fakes;
+
+go_bandit([](){
+
+ describe("before_each/after_each", [&](){
+ std::unique_ptr<bandit::detail::contextstack_t> context_stack;
+ std::unique_ptr<bf::fake_context> context;
+
+ before_each([&](){
+ context = std::unique_ptr<bf::fake_context>(new bf::fake_context());
+ context_stack = std::unique_ptr<bandit::detail::contextstack_t>(new bandit::detail::contextstack_t());
+ context_stack->push_back(context.get());
+ });
+
+ describe("before_each", [&](){
+ bandit::detail::voidfunc_t before_each_fn;
+
+ before_each([&](){
+ before_each_fn = [](){};
+ });
+
+ it("registers itself for the current context in the stack", [&](){
+ before_each(before_each_fn, *context_stack);
+ Assert::That(context->call_log(), Has().Exactly(1).EqualTo("register_before_each"));
+ });
+
+ });
+
+ describe("after_each", [&](){
+ bandit::detail::voidfunc_t after_each_fn;
+
+ before_each([&](){
+ after_each_fn = [](){};
+ });
+
+ it("registers itself for the current context in the stack", [&](){
+ after_each(after_each_fn, *context_stack);
+ Assert::That(context->call_log(), Has().Exactly(1).EqualTo("register_after_each"));
+ });
+
+ });
+ });
+
+ describe("before_each/after_each integration", [&](){
+ bandit::specs::logging_fake logger;
+
+ before_each([&](){
+ logger.log() << "first before_each called" << std::endl;
+ });
+
+ before_each([&](){
+ logger.log() << "second before_each called" << std::endl;
+ });
+
+ after_each([&](){
+ logger.log() << "first after_each called" << std::endl;
+ });
+
+ after_each([&](){
+ logger.log() << "second after_each called" << std::endl;
+ });
+
+ it("should only have called the before_each functions for the first test", [&](){
+ Assert::That(logger.call_log(), Has().Exactly(1).EqualTo("first before_each called"));
+ Assert::That(logger.call_log(), Has().Exactly(1).EqualTo("second before_each called"));
+ Assert::That(logger.call_log(), Has().None().Containing("after_each"));
+ });
+
+ it("should have called 'before_each' function twice, and 'after_each' functions once for the second test", [&](){
+ Assert::That(logger.call_log(), Has().Exactly(2).EqualTo("first before_each called"));
+ Assert::That(logger.call_log(), Has().Exactly(2).EqualTo("second before_each called"));
+ Assert::That(logger.call_log(), Has().Exactly(1).EqualTo("first after_each called"));
+ Assert::That(logger.call_log(), Has().Exactly(1).EqualTo("second after_each called"));
+ });
+ });
+});
diff --git a/vendor/bandit/specs/context.spec.cpp b/vendor/bandit/specs/context.spec.cpp
new file mode 100644
index 00000000..d517ef80
--- /dev/null
+++ b/vendor/bandit/specs/context.spec.cpp
@@ -0,0 +1,44 @@
+#include <specs/specs.h>
+
+go_bandit([](){
+
+ describe("bandit_context:", [&](){
+
+ std::unique_ptr<bandit::detail::bandit_context> context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ context = std::unique_ptr<bandit::detail::bandit_context>(
+ new bandit::detail::bandit_context("context name", hard_skip));
+ });
+
+ it("is ok to register before_each as it is not executing", [&](){
+ context->register_before_each([](){});
+ });
+
+ it("is ok to register after_each as it is not executing", [&](){
+ context->register_after_each([](){});
+ });
+
+ describe("is executing", [&](){
+
+ before_each([&](){
+ context->execution_is_starting();
+ });
+
+ it("is not ok to register before_each", [&](){
+ AssertThrows(bandit::detail::test_run_error, context->register_before_each([](){}));
+ Assert::That(LastException<bandit::detail::test_run_error>().what(),
+ Equals("before_each was called after 'describe' or 'it'"));
+ });
+
+ it("is not ok to register after_each", [&](){
+ AssertThrows(bandit::detail::test_run_error, context->register_after_each([](){}));
+ Assert::That(LastException<bandit::detail::test_run_error>().what(),
+ Equals("after_each was called after 'describe' or 'it'"));
+ });
+ });
+
+ });
+
+});
diff --git a/vendor/bandit/specs/describe.spec.cpp b/vendor/bandit/specs/describe.spec.cpp
new file mode 100644
index 00000000..d4600a28
--- /dev/null
+++ b/vendor/bandit/specs/describe.spec.cpp
@@ -0,0 +1,117 @@
+#include <specs/specs.h>
+
+using namespace bandit::fakes;
+namespace bd = bandit::detail;
+
+SPEC_BEGIN(describe)
+
+ describe("describe:", [](){
+ bandit::detail::voidfunc_t describe_fn;
+ fake_reporter_ptr reporter;
+ std::unique_ptr<bd::contextstack_t> context_stack;
+ std::unique_ptr<fake_context> global_context;
+
+ before_each([&](){
+ reporter = fake_reporter_ptr(new fake_reporter());
+
+ context_stack = std::unique_ptr<bd::contextstack_t>(new bd::contextstack_t());
+
+ global_context = std::unique_ptr<fake_context>(new fake_context());
+ context_stack->push_back(global_context.get());
+ });
+
+
+ auto call_describe = [&](){
+ describe("context name", describe_fn, *reporter, *context_stack);
+ };
+
+ describe("with a succeeding 'it'", [&](){
+ int context_stack_size_while_running;
+
+ before_each([&](){
+ context_stack_size_while_running = 0;
+ describe_fn = [&](){context_stack_size_while_running = context_stack->size();};
+ });
+
+ it("tells its parent context that execution has started", [&](){
+ // This is important as once execution has started,
+ // before_each and after_each calls cannot be guaranteed to
+ // be run before any 'it' method.
+
+ call_describe();
+ AssertThat(global_context->call_log(), Has().AtLeast(1).EqualTo("execution_is_starting"));
+ });
+
+ it("tells reporter it's starting a run", [&](){
+ call_describe();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("context_starting: context name"));
+ });
+
+ it("tells reporter it's finished a run", [&](){
+ call_describe();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("context_ended: context name"));
+ });
+
+ it("pushes a new context during execution", [&](){
+ call_describe();
+ AssertThat(context_stack_size_while_running, Equals(2));
+ });
+
+ it("pops the context from the stack after execution so that only the global context is left", [&](){
+ call_describe();
+ AssertThat(*context_stack, Is().OfLength(1));
+ });
+
+ });
+
+ describe("with test run error", [&](){
+ //
+ // This can occur if after_each or before_each are called
+ // after execution has started for a context.
+ //
+
+ before_each([&](){
+ describe_fn = [&](){ throw bandit::detail::test_run_error("we dun goofed!"); };
+ });
+
+ it("doesn't propagate the error", [&](){
+ call_describe();
+ });
+
+ it("tells reporter to report the error", [&](){
+ call_describe();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("test_run_error: context name (we dun goofed!)"));
+ });
+
+ });
+
+ describe("skip", [&](){
+ bool context_is_hard_skip;
+ describe_fn =
+ [&](){ context_is_hard_skip = context_stack->back()->hard_skip(); };
+
+ before_each([&](){
+ context_is_hard_skip = false;
+ });
+
+ describe("describe_skip", [&](){
+
+ it("pushes a context marked as skipped on the stack", [&](){
+ describe_skip("context name", describe_fn, *reporter, *context_stack);
+ AssertThat(context_is_hard_skip, IsTrue());
+ });
+
+ });
+
+ describe("xdescribe", [&](){
+
+ it("pushes a context marked as skipped on the stack", [&](){
+ xdescribe("context name", describe_fn, *reporter, *context_stack);
+ AssertThat(context_is_hard_skip, IsTrue());
+ });
+
+ });
+ });
+ });
+
+SPEC_END
diff --git a/vendor/bandit/specs/failure_formatters/default_formatter.spec.cpp b/vendor/bandit/specs/failure_formatters/default_formatter.spec.cpp
new file mode 100644
index 00000000..6d29b694
--- /dev/null
+++ b/vendor/bandit/specs/failure_formatters/default_formatter.spec.cpp
@@ -0,0 +1,21 @@
+#include <specs/specs.h>
+namespace bd = bandit::detail;
+
+go_bandit([](){
+
+ describe("default failure formatter", [&](){
+ bd::default_failure_formatter formatter;
+
+ it("formats assertions with file and line number", [&](){
+ bd::assertion_exception exception("message", "file", 321);
+ AssertThat(formatter.format(exception), Equals("file:321: message"));
+ });
+
+ it("formats assertions without file and line number", [&](){
+ bd::assertion_exception exception("message");
+ AssertThat(formatter.format(exception), Equals("message"));
+ });
+
+ });
+
+});
diff --git a/vendor/bandit/specs/failure_formatters/visual_studio_failure_formatter.spec.cpp b/vendor/bandit/specs/failure_formatters/visual_studio_failure_formatter.spec.cpp
new file mode 100644
index 00000000..0d283c8e
--- /dev/null
+++ b/vendor/bandit/specs/failure_formatters/visual_studio_failure_formatter.spec.cpp
@@ -0,0 +1,22 @@
+#include <specs/specs.h>
+namespace bd = bandit::detail;
+
+go_bandit([](){
+
+ describe("Visual Studio failure formatter:", [&](){
+
+ bd::visual_studio_failure_formatter formatter;
+
+ it("formats assertions with file and line number", [&](){
+ bd::assertion_exception exception("message", "file", 321);
+ AssertThat(formatter.format(exception), Equals("file(321): message"));
+ });
+
+ it("formats assertions without file and line number", [&](){
+ bd::assertion_exception exception("message");
+ AssertThat(formatter.format(exception), Equals("bandit: message"));
+ });
+
+ });
+
+});
diff --git a/vendor/bandit/specs/fakes/fake_context.h b/vendor/bandit/specs/fakes/fake_context.h
new file mode 100644
index 00000000..e5d1d870
--- /dev/null
+++ b/vendor/bandit/specs/fakes/fake_context.h
@@ -0,0 +1,69 @@
+#ifndef BANDIT_FAKE_CONTEXT_H
+#define BANDIT_FAKE_CONTEXT_H
+
+namespace bandit { namespace fakes {
+
+ struct fake_context : public bandit::detail::context, public bandit::specs::logging_fake
+ {
+ fake_context() : hard_skip_(false), name_("fake_context"),
+ custom_after_each_([](){}), custom_before_each_([](){})
+ {}
+
+ const std::string& name()
+ {
+ log() << "name" << std::endl;
+ return name_;
+ }
+
+ void execution_is_starting()
+ {
+ log() << "execution_is_starting" << std::endl;
+ }
+
+ void register_before_each(detail::voidfunc_t)
+ {
+ log() << "register_before_each" << std::endl;
+ }
+
+ void register_after_each(detail::voidfunc_t)
+ {
+ log() << "register_after_each" << std::endl;
+ }
+
+ void run_before_eaches()
+ {
+ log() << "run_before_eaches" << std::endl;
+ custom_before_each_();
+ }
+
+ void run_after_eaches()
+ {
+ log() << "run_after_eaches" << std::endl;
+ custom_after_each_();
+ }
+
+ bool hard_skip()
+ {
+ log() << "hard_skip: returning " << hard_skip_ << std::endl;
+ return hard_skip_;
+ }
+
+ void with_after_each(detail::voidfunc_t call)
+ {
+ custom_after_each_ = call;
+ }
+
+ void with_before_each(detail::voidfunc_t call)
+ {
+ custom_before_each_ = call;
+ }
+
+ private:
+ bool hard_skip_;
+ std::string name_;
+ detail::voidfunc_t custom_after_each_;
+ detail::voidfunc_t custom_before_each_;
+ };
+}}
+
+#endif
diff --git a/vendor/bandit/specs/fakes/fake_reporter.h b/vendor/bandit/specs/fakes/fake_reporter.h
new file mode 100644
index 00000000..032ed44d
--- /dev/null
+++ b/vendor/bandit/specs/fakes/fake_reporter.h
@@ -0,0 +1,78 @@
+#ifndef BANDIT_SPECS_FAKE_REPORTER_H
+#define BANDIT_SPECS_FAKE_REPORTER_H
+
+namespace bandit { namespace fakes {
+ struct fake_reporter :
+ public bandit::detail::listener,
+ public bandit::specs::logging_fake
+ {
+ fake_reporter() : test_run_status_(true)
+ {}
+
+ void test_run_starting()
+ {
+ log() << "test_run_starting" << std::endl;
+ }
+
+ void test_run_complete()
+ {
+ log() << "test_run_complete" << std::endl;
+ }
+
+ void context_starting(const char* desc)
+ {
+ log() << "context_starting: " << desc << std::endl;
+ }
+
+ void context_ended(const char* desc)
+ {
+ log() << "context_ended: " << desc << std::endl;
+ }
+
+ void test_run_error(const char* desc, const struct bandit::detail::test_run_error& err)
+ {
+ log() << "test_run_error: " << desc << " (" << strip_newline(err.what()) << ")" << std::endl;
+ }
+
+ void it_starting(const char* desc)
+ {
+ log() << "it_starting: " << desc << std::endl;
+ }
+
+ void it_succeeded(const char* desc)
+ {
+ log() << "it_succeeded: " << desc << std::endl;
+ }
+
+ void it_failed(const char* desc, const bandit::detail::assertion_exception& ex)
+ {
+ log() << "it_failed: " << desc << " (" << strip_newline(ex.what()) << ")" << std::endl;
+ }
+
+ void it_unknown_error(const char* desc)
+ {
+ log() << "it_unknown_error: " << desc << std::endl;
+ }
+
+ void it_skip(const char* desc)
+ {
+ log() << "it_skip: " << desc << std::endl;
+ }
+
+ bool did_we_pass() const
+ {
+ return test_run_status_;
+ }
+
+ void set_test_run_status(bool status)
+ {
+ test_run_status_ = status;
+ }
+
+ private:
+ bool test_run_status_;
+ };
+ typedef std::unique_ptr<fake_reporter> fake_reporter_ptr;
+}}
+
+#endif
diff --git a/vendor/bandit/specs/fakes/fakes.h b/vendor/bandit/specs/fakes/fakes.h
new file mode 100644
index 00000000..a48517f6
--- /dev/null
+++ b/vendor/bandit/specs/fakes/fakes.h
@@ -0,0 +1,8 @@
+#ifndef BANDIT_SPECS_FAKES_H
+#define BANDIT_SPECS_FAKES_H
+
+#include <specs/fakes/logging_fake.h>
+#include <specs/fakes/fake_reporter.h>
+#include <specs/fakes/fake_context.h>
+
+#endif
diff --git a/vendor/bandit/specs/fakes/logging_fake.h b/vendor/bandit/specs/fakes/logging_fake.h
new file mode 100644
index 00000000..ac1d3dd0
--- /dev/null
+++ b/vendor/bandit/specs/fakes/logging_fake.h
@@ -0,0 +1,32 @@
+#ifndef BANDIT_SPECS_LOGGING_FAKE_H
+#define BANDIT_SPECS_LOGGING_FAKE_H
+#include <sstream>
+
+namespace bandit { namespace specs {
+
+ struct logging_fake
+ {
+ std::ostream& log()
+ {
+ return logstm_;
+ }
+
+ std::string strip_newline(const char* val)
+ {
+ std::string no_newline = val;
+ std::transform(no_newline.begin(), no_newline.end(), no_newline.begin(), [](const char& c) {
+ return (c == '\n' || c == '\r') ? ' ' : c;
+ });
+ return no_newline;
+ }
+
+ std::string call_log()
+ {
+ return logstm_.str();
+ }
+
+ private:
+ std::stringstream logstm_;
+ };
+}}
+#endif
diff --git a/vendor/bandit/specs/fuzzbox.spec.cpp b/vendor/bandit/specs/fuzzbox.spec.cpp
new file mode 100644
index 00000000..6515a554
--- /dev/null
+++ b/vendor/bandit/specs/fuzzbox.spec.cpp
@@ -0,0 +1,77 @@
+#include <specs/specs.h>
+
+namespace fuzzbox {
+
+ typedef enum {
+ clean,
+ distorted
+ } sounds;
+
+ struct fuzzbox
+ {
+ fuzzbox() : sound_(sounds::clean)
+ {}
+
+ void flip()
+ {
+ sound_ = sounds::distorted;
+ }
+
+ sounds sound()
+ {
+ return sound_;
+ }
+
+ private:
+ sounds sound_;
+ };
+ typedef std::unique_ptr<fuzzbox> fuzzbox_ptr;
+
+ struct guitar
+ {
+ void add_effect(fuzzbox* effect)
+ {
+ effect_ = effect;
+ }
+
+ sounds sound()
+ {
+ return effect_->sound();
+ }
+
+ private:
+ fuzzbox* effect_;
+ };
+ typedef std::unique_ptr<guitar> guitar_ptr;
+
+go_bandit([](){
+
+ describe("fuzzbox:", [](){
+ guitar_ptr guitar;
+ fuzzbox_ptr fuzzbox;
+
+ before_each([&](){
+ guitar = guitar_ptr(new struct guitar());
+ fuzzbox = fuzzbox_ptr(new struct fuzzbox());
+ guitar->add_effect(fuzzbox.get());
+ });
+
+ it("starts in clean mode", [&](){
+ AssertThat(guitar->sound(), Equals(sounds::clean));
+ });
+
+ describe("in distorted mode", [&](){
+
+ before_each([&](){
+ fuzzbox->flip();
+ });
+
+ it("sounds distorted", [&](){
+ AssertThat(guitar->sound(), Equals(sounds::distorted));
+ });
+ });
+ });
+
+});
+
+}
diff --git a/vendor/bandit/specs/it.spec.cpp b/vendor/bandit/specs/it.spec.cpp
new file mode 100644
index 00000000..287a1ede
--- /dev/null
+++ b/vendor/bandit/specs/it.spec.cpp
@@ -0,0 +1,355 @@
+#include <specs/specs.h>
+using namespace bandit::fakes;
+namespace bd = bandit::detail;
+
+go_bandit([](){
+ describe("it:", [&](){
+ bd::voidfunc_t it_func;
+ fake_reporter_ptr reporter;
+ std::unique_ptr<bd::contextstack_t> contexts;
+ std::unique_ptr<fake_context> context;
+ bandit::adapters::snowhouse_adapter assertion_adapter;
+ bd::run_policy_ptr run_policy;
+
+ before_each([&](){
+ reporter = fake_reporter_ptr(new fake_reporter());
+ contexts = std::unique_ptr<bd::contextstack_t>(new bd::contextstack_t());
+ context = std::unique_ptr<fake_context>(new fake_context());
+ contexts->push_back(context.get());
+
+ run_policy = bd::run_policy_ptr(new bd::always_run_policy());
+ });
+
+ auto call_it = [&]() {
+ it("my it", it_func, *reporter, *contexts, assertion_adapter, *run_policy);
+ };
+
+ it("tells the current context that execution has started", [&](){
+ // This is important as once execution has started,
+ // before_each and after_each calls cannot be guaranteed to
+ // be run before any 'it' method.
+
+ call_it();
+ AssertThat(context->call_log(), Has().AtLeast(1).EqualTo("execution_is_starting"));
+ });
+
+ describe("with succeeding test", [&](){
+ before_each([&](){
+ it_func = [](){};
+ });
+
+ it("tells reporter it's starting", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_starting: my it"));
+ });
+
+ it("tells reporter it's succeeded", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_succeeded: my it"));
+ });
+
+ it("calls before_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_before_eaches"));
+ });
+
+ it("calls after_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_after_eaches"));
+ });
+
+ describe("but with a failing after_each", [&](){
+
+ before_each([&](){
+ context->with_after_each([](){ AssertThat(2, Equals(3)); });
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_failed: my it (Expected: equal to 3 Actual: 2 )"));
+ });
+
+ it("doesn't report a succeeding test", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().None().EqualTo("it_succeeded: my it"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+ });
+
+ describe("but with a std::exception in after_each", [&](){
+
+ before_each([&](){
+ context->with_after_each([](){ throw std::logic_error("logic is wrong!"); });
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_failed: my it (exception: logic is wrong!)"));
+ });
+
+ it("doesn't report a succeeding test", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().None().EqualTo("it_succeeded: my it"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+
+ });
+
+ describe("but with an unknown error in after_each", [&](){
+
+ before_each([&](){
+ context->with_after_each([](){ throw 25; });
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_unknown_error: my it"));
+ });
+
+ it("doesn't report a succeeding test", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().None().EqualTo("it_succeeded: my it"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+ });
+
+ describe("but with a failing before_each", [&](){
+
+ before_each([&](){
+ context->with_before_each([](){ AssertThat(2, Equals(3)); });
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_failed: my it (Expected: equal to 3 Actual: 2 )"));
+ });
+
+ it("doesn't report a succeeding test", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().None().EqualTo("it_succeeded: my it"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+ });
+
+ describe("but with a std::exception in before_each", [&](){
+
+ before_each([&](){
+ context->with_before_each([](){ throw std::logic_error("logic is wrong!"); });
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_failed: my it (exception: logic is wrong!)"));
+ });
+
+ it("doesn't report a succeeding test", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().None().EqualTo("it_succeeded: my it"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+ });
+
+ describe("but with an unknown error in before_each", [&](){
+
+ before_each([&](){
+ context->with_before_each([](){ throw 25; });
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_unknown_error: my it"));
+ });
+
+ it("doesn't report a succeeding test", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().None().EqualTo("it_succeeded: my it"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+ });
+
+ });
+
+ describe("with failing test", [&](){
+ before_each([&](){
+ it_func = [](){ AssertThat(3, Equals(2)); };
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_failed: my it (Expected: equal to 2 Actual: 3 )"));
+ });
+
+ it("calls before_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_before_eaches"));
+ });
+
+ it("calls after_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_after_eaches"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+ });
+
+
+ describe("with crashing test", [&](){
+ before_each([&](){
+ it_func = [](){ throw 44; };
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_unknown_error: my it"));
+ });
+
+ it("calls before_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_before_eaches"));
+ });
+
+ it("calls after_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_after_eaches"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+ });
+
+ describe("with test throwing exception based on 'std::exception'", [&](){
+
+ before_each([&](){
+ it_func = [](){ throw std::logic_error("logic error"); };
+ });
+
+ it("tells reporter it's failed", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_failed: my it (exception: logic error)"));
+ });
+
+ it("calls before_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_before_eaches"));
+ });
+
+ it("calls after_each in context", [&](){
+ call_it();
+ AssertThat(context->call_log(), Has().Exactly(1).EqualTo("run_after_eaches"));
+ });
+
+ it("tells run_policy that we have a failing test", [&](){
+ call_it();
+ AssertThat(run_policy->has_encountered_failure(), IsTrue());
+ });
+
+ });
+
+ describe("it_skip", [&](){
+
+ it("tells reporter it's skipped", [&](){
+ it_skip("my it", [](){}, *reporter);
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_skip: my it"));
+ });
+
+ it("doesn't call function", [&](){
+ bool called = false;
+ it_skip("my it", [&](){ called = true; }, *reporter);
+ AssertThat(called, IsFalse());
+ });
+
+ });
+
+ describe("xit", [&](){
+
+ it("tells reporter it's skipped", [&](){
+ xit("my it", [](){}, *reporter);
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_skip: my it"));
+ });
+
+ it("doesn't call function", [&](){
+ bool called = false;
+ xit("my it", [&](){ called = true; }, *reporter);
+ AssertThat(called, IsFalse());
+ });
+
+ });
+
+ describe("with a run policy that says to skip this 'it'", [&](){
+ bool it_was_called;
+
+ before_each([&](){
+ run_policy = bd::run_policy_ptr(new bd::never_run_policy());
+ it_func = [&](){ it_was_called = true; };
+ it_was_called = false;
+ });
+
+ it("tells reporter it's skipped", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_skip: my it"));
+ });
+
+ it("doesn't call function", [&](){
+ call_it();
+ AssertThat(it_was_called, IsFalse());
+ });
+
+ });
+
+ describe("skipping", [&](){
+ bool it_was_called;
+
+ before_each([&](){
+ it_func = [&](){ it_was_called = true; };
+ it_was_called = false;
+ });
+
+ describe("with a policy that says to skip this it", [&](){
+
+ before_each([&](){
+ run_policy = bd::run_policy_ptr(new bd::never_run_policy());
+ });
+
+ it("tells reporter it's skipped", [&](){
+ call_it();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("it_skip: my it"));
+ });
+
+ it("doesn't call function", [&](){
+ call_it();
+ AssertThat(it_was_called, IsFalse());
+ });
+
+ });
+ });
+ });
+});
diff --git a/vendor/bandit/specs/main.cpp b/vendor/bandit/specs/main.cpp
new file mode 100644
index 00000000..dde5de2d
--- /dev/null
+++ b/vendor/bandit/specs/main.cpp
@@ -0,0 +1,6 @@
+#include <specs/specs.h>
+
+int main(int argc, char* argv[])
+{
+ return bandit::run(argc, argv);
+}
diff --git a/vendor/bandit/specs/matchers/be_close_to.cpp b/vendor/bandit/specs/matchers/be_close_to.cpp
new file mode 100644
index 00000000..64309673
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_close_to.cpp
@@ -0,0 +1,112 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeCloseTo)
+
+describe("be_close_to matcher", []{
+ describe("when the actual value is declared as a float", [&]{
+ float actualValue = 2.0 / 3.0;
+
+ describe("and the expected value is also a float", [&]{
+ float expectedValue;
+
+ describe("with an explicit threshold", [&]{
+ float threshold = 0.1;
+
+ describe("and the values are within the given threshold", [&]{
+ before_each([&]{
+ expectedValue = 2.0 / 3.0 + 0.01;
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must be_close_to(expectedValue).within(threshold);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_close_to(expectedValue).within(threshold); }());
+ });
+ });
+
+ describe("and the values are not within the given threshold", [&]{
+ before_each([&]{
+ expectedValue = 2.0 / 3.0 + 0.2;
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not be_close_to(expectedValue).within(threshold);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_close_to(expectedValue).within(threshold); }());
+ });
+ });
+ });
+
+ describe("without an explicit threshold", [&]{
+ describe("and the values are within the default threshold", [&]{
+ before_each([&]{
+ expectedValue = 2.0 / 3.0 + 0.000001;
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must be_close_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_close_to(expectedValue); }());
+ });
+ });
+
+ describe("and the values are not within the default threshold", [&]{
+ before_each([&]{
+ expectedValue = 2.0 / 3.0 + 0.1;
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not be_close_to(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_close_to(expectedValue); }());
+ });
+ });
+ });
+ });
+
+ describe("and the expected value is a compatible non-float type", [&]{
+ int expectedValue;
+ float threshold = 1;
+
+ describe("and the values are within the given threshold", [&]{
+ before_each([&]{
+ expectedValue = 1;
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must be_close_to(expectedValue).within(threshold);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_close_to(expectedValue).within(threshold); }());
+ });
+ });
+
+ describe("and the values are not within the given threshold", [&]{
+ before_each([&]{
+ expectedValue = 5;
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not be_close_to(expectedValue).within(threshold);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_close_to(expectedValue).within(threshold); }());
+ });
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_empty.cpp b/vendor/bandit/specs/matchers/be_empty.cpp
new file mode 100644
index 00000000..3ed4a6f9
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_empty.cpp
@@ -0,0 +1,89 @@
+#include <set>
+
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeEmpty)
+
+describe("be_empty matcher", [&]{
+ describe("when the value is an STL vector", [&]{
+ describe("which is empty", [&]{
+ std::vector<int> container;
+
+ it("must pass a positive match", [&]{
+ container must be_empty;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not be_empty; }());
+ });
+ });
+
+ describe("which is not empty", [&]{
+ std::vector<int> container {2, 7};
+
+ it("must pass a negative match", [&]{
+ container must_not be_empty;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must be_empty; }());
+ });
+ });
+ });
+
+ describe("when the value is an STL map", [&]{
+ describe("which is empty", [&]{
+ std::map<int, int> container;
+
+ it("must pass a positive match", [&]{
+ container must be_empty;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not be_empty; }());
+ });
+ });
+
+ describe("which is not empty", [&]{
+ std::map<int, int> container {{5, 6}, {7,10}};
+
+ it("must pass a negative match", [&]{
+ container must_not be_empty;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must be_empty; }());
+ });
+ });
+ });
+
+ describe("when the value is an STL set", [&]{
+ describe("which is empty", [&]{
+ std::set<int> container;
+
+ it("must pass a positive match", [&]{
+ container must be_empty;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not be_empty; }());
+ });
+ });
+
+ describe("which is not empty", [&]{
+ std::set<int> container {5, 7};
+
+ it("must pass a negative match", [&]{
+ container must_not be_empty;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must be_empty; }());
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_falsy.cpp b/vendor/bandit/specs/matchers/be_falsy.cpp
new file mode 100644
index 00000000..d8c71c1b
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_falsy.cpp
@@ -0,0 +1,85 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeFalsy)
+
+describe("be_falsy matcher", [&]{
+ describe("when the value is a built-in type", [&]{
+ bool value;
+
+ describe("which evaluates to false", [&]{
+ before_each([&]{
+ value = false;
+ });
+
+ it("must accept a positive match", [&]{
+ value must be_falsy;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ value must_not be_falsy; }());
+ });
+ });
+
+ describe("which evaluates to true", [&]{
+ before_each([&]{
+ value = true;
+ });
+
+ it("must accept a negative match", [&]{
+ value must_not be_falsy;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ value must be_falsy; }());
+ });
+ });
+ });
+
+ describe("when the value is nullptr", [&]{
+ auto value = nullptr;
+
+ it("must accept a positive match", [&]{
+ value must be_falsy;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ value must_not be_falsy; }());
+ });
+ });
+
+ describe("when the value is a pointer", [&]{
+ char* value;
+
+ describe("which evaluates to false", [&]{
+ before_each([&]{
+ value = NULL;
+ });
+
+ it("must accept a positive match", [&]{
+ value must be_falsy;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ value must_not be_falsy; }());
+ });
+ });
+
+ describe("which evaluates to true", [&]{
+ before_each([&]{
+ value = (char*)"cat";
+ });
+
+ it("must accept a negative match", [&]{
+ value must_not be_falsy;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ value must be_falsy; }());
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_greater_than.cpp b/vendor/bandit/specs/matchers/be_greater_than.cpp
new file mode 100644
index 00000000..17a97fe3
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_greater_than.cpp
@@ -0,0 +1,105 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeGreaterThan)
+
+describe("be_greater_than matcher", []{
+ describe("when the actual value is a built-in type", [&]{
+ int actualValue = 10;
+
+ describe("and the expected value is the same built-in type", [&]{
+ int expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_greater_than(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_greater_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_greater_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_greater_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = actualValue;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_greater_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_greater_than(expectedValue); }());
+ });
+ });
+ });
+
+ describe("and the expected value is a different, but comparable, built-in type", [&]{
+ float expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1.1;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_greater_than(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_greater_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100.1;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_greater_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_greater_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = actualValue;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_greater_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_greater_than(expectedValue); }());
+ });
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_gte.cpp b/vendor/bandit/specs/matchers/be_gte.cpp
new file mode 100644
index 00000000..f0e18313
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_gte.cpp
@@ -0,0 +1,120 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+
+SPEC_BEGIN(Matchers::BeGTE)
+
+describe("be_gte matcher", [&]{
+ int someInteger = 10;
+
+ describe("when the actual value is a built-in type", [&]{
+ int actualValue = someInteger;
+
+ describe("and the expected value is the same built-in type", [&]{
+ int expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_gte(expectedValue);
+ actualValue must be_greater_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_gte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_greater_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_gte(expectedValue);
+ actualValue must_not be_greater_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_gte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must be_greater_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = actualValue;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_gte(expectedValue);
+ actualValue must be_greater_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_gte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_greater_than_or_equal_to(expectedValue); }());
+ });
+ });
+ });
+
+ describe("and the expected value is a different, but comparable, built-in type", [&]{
+ float expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1.1;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_gte(expectedValue);
+ actualValue must be_greater_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_gte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_greater_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100.1;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_gte(expectedValue);
+ actualValue must_not be_greater_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_gte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must be_greater_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = someInteger / 1.0;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_gte(expectedValue);
+ actualValue must be_greater_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_gte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_greater_than_or_equal_to(expectedValue); }());
+ });
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_less_than.cpp b/vendor/bandit/specs/matchers/be_less_than.cpp
new file mode 100644
index 00000000..30f60c47
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_less_than.cpp
@@ -0,0 +1,105 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeLessThan)
+
+describe("be_less_than matcher", []{
+ describe("when the actual value is a built-in type", [&]{
+ int actualValue = 10;
+
+ describe("and the expected value is the same built-in type", [&]{
+ int expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_less_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_less_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_less_than(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_less_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = actualValue;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_less_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_less_than(expectedValue); }());
+ });
+ });
+ });
+
+ describe("and the expected value is a different, but comparable, built-in type", [&]{
+ float expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1.1;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_less_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_less_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100.1;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_less_than(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_less_than(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = actualValue;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_less_than(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_less_than(expectedValue); }());
+ });
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_lte.cpp b/vendor/bandit/specs/matchers/be_lte.cpp
new file mode 100644
index 00000000..443ac1c5
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_lte.cpp
@@ -0,0 +1,119 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeLTE)
+
+describe("be_lte matcher", [&]{
+ int someInteger = 10;
+
+ describe("when the actual value is a built-in type", [&]{
+ int actualValue = someInteger;
+
+ describe("and the expected value is the same built-in type", [&]{
+ int expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_lte(expectedValue);
+ actualValue must_not be_less_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_lte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must be_less_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_lte(expectedValue);
+ actualValue must be_less_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_lte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_less_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = actualValue;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_lte(expectedValue);
+ actualValue must be_less_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_lte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_less_than_or_equal_to(expectedValue); }());
+ });
+ });
+ });
+
+ describe("and the expected value is a different, but comparable, built-in type", [&]{
+ float expectedValue;
+
+ describe("and the actual value is greater than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 1.1;
+ });
+
+ it("must pass a negative match", [&]{
+ actualValue must_not be_lte(expectedValue);
+ actualValue must_not be_less_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must be_lte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must be_less_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value is less than the expected value", [&]{
+ before_each([&]{
+ expectedValue = 100.1;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_lte(expectedValue);
+ actualValue must be_less_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_lte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_less_than_or_equal_to(expectedValue); }());
+ });
+ });
+
+ describe("and the actual value equals the expected value", [&]{
+ before_each([&]{
+ expectedValue = someInteger / 1.0;
+ });
+
+ it("must pass a positive match", [&]{
+ actualValue must be_lte(expectedValue);
+ actualValue must be_less_than_or_equal_to(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not be_lte(expectedValue); }());
+ AssertThrows(std::exception, [&]{ actualValue must_not be_less_than_or_equal_to(expectedValue); }());
+ });
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_null.cpp b/vendor/bandit/specs/matchers/be_null.cpp
new file mode 100644
index 00000000..ae3cd40d
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_null.cpp
@@ -0,0 +1,43 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeNull)
+
+describe("be_null matcher", [&]{
+ describe("when the value is a pointer to a built-in type", [&]{
+ int* value;
+
+ describe("which is NULL", [&]{
+ before_each([&]{
+ value = NULL;
+ });
+
+ it("must pass a positive match", [&]{
+ value must be_null;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ value must_not be_null; }());
+ });
+ });
+
+ describe("which is not NULL", [&]{
+ int i = 7;
+
+ before_each([&]{
+ value = &i;
+ });
+
+ it("must pass a negative match", [&]{
+ value must_not be_null;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ value must be_null; }());
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/be_truthy.cpp b/vendor/bandit/specs/matchers/be_truthy.cpp
new file mode 100644
index 00000000..5e583fbf
--- /dev/null
+++ b/vendor/bandit/specs/matchers/be_truthy.cpp
@@ -0,0 +1,85 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::BeTruthy)
+
+describe("be_truthy matcher", [&]{
+ describe("when the value is a built-in type", [&]{
+ bool value;
+
+ describe("which evaluates to false", [&]{
+ before_each([&]{
+ value = false;
+ });
+
+ it("must accept a negative match", [&]{
+ value must_not be_truthy;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ value must be_truthy; }());
+ });
+ });
+
+ describe("which evaluates to true", [&]{
+ before_each([&]{
+ value = true;
+ });
+
+ it("must accept a positive match", [&]{
+ value must be_truthy;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ value must_not be_truthy; }());
+ });
+ });
+ });
+
+ describe("when the value is nullptr", [&]{
+ auto value = nullptr;
+
+ it("must accept a negative match", [&]{
+ value must_not be_truthy;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ value must be_truthy; }());
+ });
+ });
+
+ describe("when the value is a pointer", [&]{
+ char* value;
+
+ describe("which evaluates to false", [&]{
+ before_each([&]{
+ value = NULL;
+ });
+
+ it("must accept a negative match", [&]{
+ value must_not be_truthy;
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ value must be_truthy; }());
+ });
+ });
+
+ describe("which evaluates to true", [&]{
+ before_each([&]{
+ value = (char*)"cat";
+ });
+
+ it("must accept a positive match", [&]{
+ value must be_truthy;
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ value must_not be_truthy; }());
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/contain.cpp b/vendor/bandit/specs/matchers/contain.cpp
new file mode 100644
index 00000000..2c0b4b3b
--- /dev/null
+++ b/vendor/bandit/specs/matchers/contain.cpp
@@ -0,0 +1,156 @@
+#include <set>
+
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::Contain)
+
+describe("contain matcher", [&]{
+ std::string element0("element0");
+ std::string element1("element1");
+
+ describe("when the container is an STL vector", [&]{
+ describe("which contains the element", [&]{
+ std::vector<std::string> container {element0, element1};
+
+ it("must pass a positive match", [&]{
+ container must contain(element1);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not contain(element1); }());
+ });
+ });
+
+ describe("which does not contain the element", [&]{
+ std::vector<int> container;
+
+ it("must pass a negative match", [&]{
+ container must_not contain(4);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must contain(4); }());
+ });
+ });
+ });
+
+ describe("when the container is an STL map", [&]{
+ describe("which contains the expected key", [&]{
+ std::map<int, int> container {{5, 6}, {7,10}};
+
+ it("must pass a positive match", [&]{
+ container must contain(5);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not contain(5); }());
+ });
+ });
+
+ describe("which does not contain the expected value", [&]{
+ std::map<int, int> container;
+
+ it("must pass a negative match", [&]{
+ container must_not contain(6);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must contain(6); }());
+ });
+ });
+ });
+
+ describe("when the container is an STL set", [&]{
+ describe("which contains the element", [&]{
+ std::set<int> container {5, 7};
+
+ it("must pass a positive match", [&]{
+ container must contain(7);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not contain(7); }());
+ });
+ });
+
+ describe("which does not contain the element", [&]{
+ std::set<int> container;
+
+ it("must pass a negative match", [&]{
+ container must_not contain(7);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must contain(7); }());
+ });
+ });
+ });
+
+ describe("when the container is a C string", [&]{
+ describe("which is null", [&]{
+ char* container = NULL;
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must contain("foo"); }());
+ });
+ });
+
+ describe("which contains the substring", [&]{
+ char* container = (char*)"jack and jill";
+ char* element = (char*)"jack";
+
+ it("must pass a positive match", [&]{
+ container must contain(element);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not contain(element); }());
+ });
+ });
+
+ describe("which does not contain the substring", [&]{
+ char* container = (char*)"batman and robin";
+ char* element = (char*)"catwoman";
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must contain(element); }());
+ });
+
+ it("must pass a negative match", [&]{
+ container must_not contain(element);
+ });
+ });
+ });
+
+ describe("when the container is a const C string", [&]{
+ describe("which contains the substring", [&]{
+ const char* container = (char*)"jack and jill";
+ const char* element = (char*)"jack";
+
+ it("must pass a positive match", [&]{
+ container must contain(element);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ container must_not contain(element); }());
+ });
+ });
+
+ describe("which does not contain the substring", [&]{
+ const char* container = (char*)"batman and robin";
+ const char* element = (char*)"catwoman";
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ container must contain(element); }());
+ });
+
+ it("must pass a negative match", [&]{
+ container must_not contain(element);
+ });
+ });
+ });
+});
+
+SPEC_END
diff --git a/vendor/bandit/specs/matchers/equal.cpp b/vendor/bandit/specs/matchers/equal.cpp
new file mode 100644
index 00000000..f7f31b0b
--- /dev/null
+++ b/vendor/bandit/specs/matchers/equal.cpp
@@ -0,0 +1,214 @@
+#include <specs/specs.h>
+
+using namespace bandit::Matchers;
+
+SPEC_BEGIN(Matchers::Equal)
+
+describe("when the actual value is a built-in type", []{
+ int actualValue = 1;
+
+ describe("and the expected value is the same built-in type", [&]{
+ int expectedValue;
+
+ describe("and the values are equal", [&]{
+ before_each([&]{
+ expectedValue = 1;
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must equal(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not equal(expectedValue); }());
+ });
+ });
+
+ describe("and the values are not equal", [&]{
+ before_each([&]{
+ expectedValue = 147;
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not equal(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must equal(expectedValue); }());
+ });
+ });
+ });
+
+ describe("and the expected value is a different, but comparable, built-in type", [&]{
+ long int expectedValue;
+
+ describe("and the values are equal", [&]{
+ before_each([&]{
+ expectedValue = 1;
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must equal(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not equal(expectedValue); }());
+ });
+ });
+
+ describe("and the values are not equal", [&]{
+ before_each([&]{
+ expectedValue = 42;
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not equal(expectedValue);
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must equal(expectedValue); }());
+ });
+ });
+ });
+});
+
+describe("when the actual value is declared as a C string", []{
+ char* actualValue = (char*)"actualValue";
+
+ describe("and the expected value is declared as a C string", [&]{
+ std::unique_ptr<char> expectedValue;
+
+ before_each([&]{
+ expectedValue.reset((char*)calloc(strlen(actualValue) + 1, sizeof(char)));
+ });
+
+ describe("and the values are equal", [&]{
+ before_each([&]{
+ stpcpy(expectedValue.get(), actualValue);
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must equal(expectedValue.get());
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not equal(expectedValue.get()); }());
+ });
+ });
+
+ describe("and the values are not equal", [&]{
+ before_each([&]{
+ stpcpy(expectedValue.get(), "expectedVal");
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not equal(expectedValue.get());
+ });
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must equal(expectedValue.get()); }());
+ });
+ });
+ });
+
+ describe("and the expected value is declared as a const C string", [&]{
+ const char *expectedValue;
+
+ describe("and the values are equal", [&]{
+ before_each([&]{
+ expectedValue = "actualValue";
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must equal(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not equal(expectedValue); }());
+ });
+ });
+ });
+
+ describe("when the expected value is a unique_ptr to a C string", [&]{
+ std::unique_ptr<char> expectedValue;
+
+ before_each([&]{
+ expectedValue.reset((char*)calloc(strlen(actualValue) + 1, sizeof(char)));
+ });
+
+ describe("and the values are equal", [&]{
+ before_each([&]{
+ stpcpy(expectedValue.get(), actualValue);
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must equal(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not equal(expectedValue); }());
+ });
+ });
+ });
+});
+
+describe("when the actual value is a unique_ptr", []{
+ std::unique_ptr<char> actualValue;
+ auto expectedValue = (char*)"expectedValue";
+
+ before_each([&]{
+ actualValue.reset((char*)calloc(strlen(expectedValue) + 1, sizeof(char)));
+ });
+
+ describe("when the strings are equal", [&]{
+ before_each([&]{
+ stpcpy(actualValue.get(), expectedValue);
+ });
+
+ it("must accept a positive match", [&]{
+ actualValue must equal(expectedValue);
+ });
+ });
+
+ describe("when the strings are not equal", [&]{
+ before_each([&]{
+ stpcpy(actualValue.get(), "hello");
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not equal(expectedValue);
+ });
+ });
+});
+
+describe("when the actual value is declared as char array", []{
+ describe("and the expected value is declared as a C string", []{
+ char actualValue[] = "actualValue";
+
+ describe("and the values are equal", [&]{
+ char* expectedValue = (char*)"actualValue";
+
+ it("must accept a positive match", [&]{
+ actualValue must equal(expectedValue);
+ });
+
+ it("must reject a negative match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must_not equal(expectedValue); }());
+ });
+ });
+
+ describe("and the values are not equal", [&]{
+ char* expectedValue = (char*)"expectedValue";
+
+ it("must reject a positive match", [&]{
+ AssertThrows(std::exception, [&]{ actualValue must equal(expectedValue); }());
+ });
+
+ it("must accept a negative match", [&]{
+ actualValue must_not equal(expectedValue);
+ });
+ });
+ });
+});
+
+SPEC_END \ No newline at end of file
diff --git a/vendor/bandit/specs/matchers/throw_exception.cpp b/vendor/bandit/specs/matchers/throw_exception.cpp
new file mode 100644
index 00000000..c7531d5f
--- /dev/null
+++ b/vendor/bandit/specs/matchers/throw_exception.cpp
@@ -0,0 +1,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
diff --git a/vendor/bandit/specs/options.spec.cpp b/vendor/bandit/specs/options.spec.cpp
new file mode 100644
index 00000000..74d057ec
--- /dev/null
+++ b/vendor/bandit/specs/options.spec.cpp
@@ -0,0 +1,121 @@
+#include <specs/specs.h>
+
+using namespace bandit::specs::util;
+namespace bd = bandit::detail;
+
+go_bandit([](){
+
+ describe("options:", [&](){
+
+ it("parses the '--help' option", [&](){
+ const char* args[] = {"executable", "--help"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+
+ AssertThat(opt.help(), IsTrue());
+ });
+
+ it("parses the '--version' option", [&](){
+ const char* args[] = {"executable", "--version"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+
+ AssertThat(opt.version(), IsTrue());
+ });
+
+ it("parses the '--no-color' option", [&](){
+ const char* args[] = {"executable", "--no-color"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+
+ AssertThat(opt.no_color(), IsTrue());
+ });
+
+ it("parser the '--formatter=vs' option", [&](){
+ const char* args[] = {"executable", "--formatter=vs"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+ AssertThat(opt.formatter(), Equals(bd::options::formatters::FORMATTER_VS));
+ });
+
+ it("parser the '--formatter=default' option", [&](){
+ const char* args[] = {"executable", "--formatter=default"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+ AssertThat(opt.formatter(), Equals(bd::options::formatters::FORMATTER_DEFAULT));
+ });
+
+ it("parses the '--skip=\"substring\"' option", [&](){
+ const char* args[] = {"executable", "--skip=substring"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+ AssertThat(opt.skip(), Equals("substring"));
+ });
+
+ it("parses skip as empty string if not present", [&](){
+ const char* args[] = {"executable"};
+ argv_helper argv(1, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+ AssertThat(opt.skip(), Equals(""));
+ });
+
+ it("parses the '--only=\"substring\"' option", [&](){
+ const char* args[] = {"executable", "--only=substring"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+ AssertThat(opt.only(), Equals("substring"));
+ });
+
+ it("parses only as empty string if not present", [&](){
+ const char* args[] = {"executable"};
+ argv_helper argv(1, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+ AssertThat(opt.only(), Equals(""));
+ });
+
+ it("parses the '--break-on-failure' oprtion", [&](){
+ const char* args[] = {"executable", "--break-on-failure"};
+ argv_helper argv(2, args);
+
+ bd::options opt(argv.argc(), argv.argv());
+
+ AssertThat(opt.break_on_failure(), IsTrue());
+ });
+
+ describe("with no arguments", [&](){
+ const char* args[] = {"executable"};
+ argv_helper argv(1, args);
+ bd::options opt(argv.argc(), argv.argv());
+
+ it("cannot find '--help'", [&](){
+ AssertThat(opt.help(), IsFalse());
+ });
+
+ it("cannot find '--version'", [&](){
+ AssertThat(opt.version(), IsFalse());
+ });
+
+ it("cannot find '--no-color'", [&](){
+ AssertThat(opt.no_color(), IsFalse());
+ });
+
+ it("cannot fine '--break-on-failure'", [&](){
+ AssertThat(opt.break_on_failure(), IsFalse())
+ });
+
+ it("uses default formatter for '--formatter'", [&](){
+ AssertThat(opt.formatter(), Equals(bd::options::formatters::FORMATTER_DEFAULT));
+ });
+ });
+ });
+
+});
diff --git a/vendor/bandit/specs/reporters/colorizer.spec.cpp b/vendor/bandit/specs/reporters/colorizer.spec.cpp
new file mode 100644
index 00000000..7708ec81
--- /dev/null
+++ b/vendor/bandit/specs/reporters/colorizer.spec.cpp
@@ -0,0 +1,45 @@
+#ifndef _WIN32
+#include <specs/specs.h>
+
+go_bandit([](){
+
+ describe("colorizer: ", [&](){
+
+ describe("colors enabled", [&](){
+ bandit::detail::colorizer colorizer;
+
+ it("can set color to green", [&](){
+ AssertThat(colorizer.green(), Equals("\033[1;32m"));
+ });
+
+ it("set color to red", [&](){
+ AssertThat(colorizer.red(), Equals("\033[1;31m"));
+ });
+ it("resets color", [&](){
+ AssertThat(colorizer.reset(), Equals("\033[0m"));
+ });
+
+ });
+
+ describe("colors disabled", [&](){
+
+ bandit::detail::colorizer colorizer(false);
+
+ it("ignores setting color to green", [&](){
+ AssertThat(colorizer.green(), Equals(""));
+ });
+
+ it("ignores setting color to red", [&](){
+ AssertThat(colorizer.red(), Equals(""));
+ });
+
+ it("ignores resetting colors", [&](){
+ AssertThat(colorizer.reset(), Equals(""));
+ });
+
+ });
+
+ });
+
+});
+#endif \ No newline at end of file
diff --git a/vendor/bandit/specs/reporters/dots_reporter.spec.cpp b/vendor/bandit/specs/reporters/dots_reporter.spec.cpp
new file mode 100644
index 00000000..f06c8d77
--- /dev/null
+++ b/vendor/bandit/specs/reporters/dots_reporter.spec.cpp
@@ -0,0 +1,202 @@
+#include <specs/specs.h>
+namespace bd = bandit::detail;
+
+go_bandit([](){
+
+ describe("dots_reporter:", [&](){
+ std::unique_ptr<std::stringstream> stm;
+ std::unique_ptr<bd::dots_reporter> reporter;
+ bd::default_failure_formatter formatter;
+ bd::colorizer colorizer(false);
+
+ before_each([&](){
+ stm = std::unique_ptr<std::stringstream>(new std::stringstream());
+ reporter = std::unique_ptr<bd::dots_reporter>(
+ new bd::dots_reporter(*stm, formatter, colorizer));
+ });
+
+ auto output = [&](){ return stm->str(); };
+
+ describe("an empty test run", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->test_run_complete();
+ });
+
+ it("reports no tests where run", [&](){
+ AssertThat(output(), Equals("\nCould not find any tests.\n"));
+ });
+
+ it("is not considered successful", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+
+ });
+
+ describe("a successful test run", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+ reporter->it_succeeded("my test");
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports a successful test run", [&](){
+ AssertThat(output(), Contains("Success!"));
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 1 succeeded.\n"));
+ });
+
+ it("displays a dot for the successful test", [&](){
+ AssertThat(output(), StartsWith("."));
+ });
+
+ it("reports a successful test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(true));
+ });
+ });
+
+ describe("a failing test run", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+
+ bd::assertion_exception exception("assertion failed!", "some_file", 123);
+ reporter->it_failed("my test", exception);
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports a failing test run in summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 0 succeeded. 1 failed.\n"));
+ });
+
+ it("reports the failed assertion", [&](){
+ AssertThat(output(), Contains("my context my test:\nsome_file:123: assertion failed!"));
+ });
+
+ it("only reports assertion failure once", [&](){
+ AssertThat(output(), Has().Exactly(1).EndingWith("assertion failed!"));
+ });
+
+ it("reports an 'F' for the failed assertion", [&](){
+ AssertThat(output(), StartsWith("F"));
+ });
+
+ it("reports a failed test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+ });
+
+ describe("a test run with a non assertion_exception thrown", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+
+ reporter->it_unknown_error("my test");
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports an 'E' for the failed test", [&](){
+ AssertThat(output(), StartsWith("E"));
+ });
+
+ it("reports the failed test", [&](){
+ AssertThat(output(), Contains("my context my test:\nUnknown exception"))
+ });
+
+ });
+
+ describe("a failing test run with nested contexts", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->context_starting("a nested context");
+ reporter->it_starting("my test");
+
+ bd::assertion_exception exception("assertion failed!", "some_file", 123);
+ reporter->it_failed("my test", exception);
+
+ reporter->context_ended("a nested context");
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports a failing test run in summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 0 succeeded. 1 failed.\n"));
+ });
+
+ it("reports the failed assertion", [&](){
+ AssertThat(output(), Contains("my context a nested context my test:\nsome_file:123: assertion failed!"));
+ });
+
+ it("reports an 'F' for the failed assertion", [&](){
+ AssertThat(output(), StartsWith("F"));
+ });
+
+ it("reports a failed test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+
+ });
+
+ describe("a context with test run errors", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+
+ bd::test_run_error error("we dun goofed!");
+ reporter->test_run_error("my context", error);
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports that the context has failed", [&](){
+ AssertThat(output(), Contains("Failed to run \"my context\": error \"we dun goofed!\""));
+ });
+
+ it("reports test run errors in summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 0 tests run. 0 succeeded. 1 test run errors.\n"))
+ });
+
+ it("reports a failed test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+ });
+
+ describe("a context with a skipped test", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+
+ reporter->it_starting("my test");
+ reporter->it_succeeded("my test");
+ reporter->it_skip("my skipped test");
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports that there is one skipped test in the summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 1 succeeded. 1 skipped.\n"));
+ });
+
+ });
+ });
+
+
+});
diff --git a/vendor/bandit/specs/reporters/single_line_reporter.spec.cpp b/vendor/bandit/specs/reporters/single_line_reporter.spec.cpp
new file mode 100644
index 00000000..ef7b5206
--- /dev/null
+++ b/vendor/bandit/specs/reporters/single_line_reporter.spec.cpp
@@ -0,0 +1,201 @@
+#include <specs/specs.h>
+namespace bd = bandit::detail;
+
+go_bandit([](){
+
+ describe("single line reporter", [&](){
+ std::unique_ptr<std::stringstream> stm;
+ std::unique_ptr<bd::single_line_reporter> reporter;
+ bd::default_failure_formatter formatter;
+ bd::colorizer colorizer(false);
+
+ before_each([&](){
+ stm = std::unique_ptr<std::stringstream>(new std::stringstream());
+ reporter = std::unique_ptr<bd::single_line_reporter>(
+ new bd::single_line_reporter(*stm, formatter, colorizer));
+ });
+
+ auto output = [&](){ return stm->str(); };
+
+ describe("an empty test run", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->test_run_complete();
+ });
+
+ it("reports that no tests were run", [&](){
+ AssertThat(output(), Equals("\nCould not find any tests.\n"));
+ });
+
+ it("is not considered successful", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+ });
+
+ describe("a successful test run", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+ reporter->it_succeeded("my test");
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports a successful test run", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 1 succeeded.\n"));
+ });
+
+ it("displays progress for the test", [&](){
+ AssertThat(output(), StartsWith("\rExecuted 0 tests."
+ "\rExecuted 1 tests."));
+ });
+
+ it("reports a successful test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(true));
+ });
+ });
+
+ describe("a failing test run", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+
+ bd::assertion_exception exception("assertion failed!", "some_file", 123);
+ reporter->it_failed("my test", exception);
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports a failing test run in summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 0 succeeded. 1 failed.\n"));
+ });
+
+ it("reports the failed assertion", [&](){
+ AssertThat(output(), Contains("my context my test:\nsome_file:123: assertion failed!"));
+ });
+
+ it("reports failing test in progress", [&](){
+ AssertThat(output(), StartsWith("\rExecuted 0 tests."
+ "\rExecuted 1 tests. 0 succeeded. 1 failed."));
+ });
+
+ it("reports a failed test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+ });
+
+ describe("a test run with a non assertion_exception thrown", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+
+ reporter->it_unknown_error("my test");
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports failing test in progress", [&](){
+ AssertThat(output(), StartsWith("\rExecuted 0 tests."
+ "\rExecuted 1 tests. 0 succeeded. 1 failed."));
+ });
+
+ it("reports the failed test", [&](){
+ AssertThat(output(), Contains("my context my test:\nUnknown exception"))
+ });
+
+ });
+
+ describe("a failing test run with nested contexts", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->context_starting("a nested context");
+ reporter->it_starting("my test");
+
+ bd::assertion_exception exception("assertion failed!", "some_file", 123);
+ reporter->it_failed("my test", exception);
+
+ reporter->context_ended("a nested context");
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports a failing test run in summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 0 succeeded. 1 failed.\n"));
+ });
+
+ it("reports the failed assertion", [&](){
+ AssertThat(output(), Contains("my context a nested context my test:\nsome_file:123: assertion failed!"));
+ });
+
+ it("displays a failed test in progress report", [&](){
+ AssertThat(output(), StartsWith("\rExecuted 0 tests."
+ "\rExecuted 1 tests. 0 succeeded. 1 failed."));
+ });
+
+ it("reports a failed test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+
+ });
+
+ describe("a context with test run errors", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+
+ bd::test_run_error error("we dun goofed!");
+ reporter->test_run_error("my context", error);
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports that the context has failed", [&](){
+ AssertThat(output(), Contains("Failed to run \"my context\": error \"we dun goofed!\""));
+ });
+
+ it("reports test run errors in summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 0 tests run. 0 succeeded. 1 test run errors.\n"))
+ });
+
+ it("reports a failed test run", [&](){
+ AssertThat(reporter->did_we_pass(), Equals(false));
+ });
+ });
+
+ describe("a context with a skipped test", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+
+ reporter->it_starting("my test");
+ reporter->it_succeeded("my test");
+ reporter->it_skip("my skipped test");
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("reports that there is one skipped test in the summary", [&](){
+ AssertThat(output(), EndsWith("Test run complete. 1 tests run. 1 succeeded. 1 skipped.\n"));
+ });
+
+ });
+
+
+ });
+
+});
diff --git a/vendor/bandit/specs/reporters/xunit_reporter.spec.cpp b/vendor/bandit/specs/reporters/xunit_reporter.spec.cpp
new file mode 100644
index 00000000..07f0c3b7
--- /dev/null
+++ b/vendor/bandit/specs/reporters/xunit_reporter.spec.cpp
@@ -0,0 +1,161 @@
+#include <specs/specs.h>
+namespace bd = bandit::detail;
+
+go_bandit([](){
+
+ describe("xunit_reporter:", [&](){
+ std::unique_ptr<std::stringstream> stm;
+ bd::default_failure_formatter formatter;
+ std::unique_ptr<bd::xunit_reporter> reporter;
+
+ auto output = [&](){ return stm->str(); };
+
+ before_each([&](){
+ stm = std::unique_ptr<std::stringstream>(new std::stringstream());
+ reporter = std::unique_ptr<bd::xunit_reporter>(new bd::xunit_reporter(*stm, formatter));
+ });
+
+ describe("an empty test run", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->test_run_complete();
+ });
+
+ it("adds a header to the output", [&](){
+ AssertThat(output(), StartsWith("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
+ });
+
+ it("outputs an empty test report", [&](){
+ AssertThat(output(), Contains(
+ "<testsuite name=\"bandit\" tests=\"0\" errors=\"0\" failures=\"0\">\n"
+ "</testsuite>\n"));
+ });
+
+ });
+
+ describe("a test run with one, successful, test", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+ reporter->it_succeeded("my test");
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("outputs info about the successful test", [&](){
+ AssertThat(output(), Contains(
+ "<testsuite name=\"bandit\" tests=\"1\" errors=\"0\" failures=\"0\">\n"
+ "\t<testcase classname=\"my context\" name=\"my test\" time=\"0\">\n"
+ "\t</testcase>\n"
+ "</testsuite>\n"));
+ });
+ });
+
+ describe("a test run with one, failing test", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+
+ bd::assertion_exception exception("assertion failed!", "some_file", 123);
+ reporter->it_failed("my test", exception);
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+
+ });
+
+ it("outputs the failing test", [&](){
+ AssertThat(output(), Contains(
+ "<testsuite name=\"bandit\" tests=\"1\" errors=\"0\" failures=\"1\">\n"
+ "\t<testcase classname=\"my context\" name=\"my test\" time=\"0\">\n"
+ "\t\t<failure message=\"some_file:123: assertion failed!\" />\n"
+ "\t</testcase>\n"
+ "</testsuite>\n"));
+ });
+
+ });
+
+ describe("a test run with one test with an unknown error", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+ reporter->it_starting("my test");
+
+ reporter->it_unknown_error("my test");
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("outputs the erroneous test", [&](){
+ AssertThat(output(), Contains(
+ "<testsuite name=\"bandit\" tests=\"1\" errors=\"0\" failures=\"1\">\n"
+ "\t<testcase classname=\"my context\" name=\"my test\" time=\"0\">\n"
+ "\t\t<failure message=\"Unknown exception\" />\n"
+ "\t</testcase>\n"
+ "</testsuite>\n"));
+ });
+
+ });
+
+ describe("a test run with one test failing with characters that need escaping", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context & < > \\ \"");
+ reporter->it_starting("my test & < > \\ \"");
+
+ bd::assertion_exception exception("assertion failed & < > \\ \"", "some_file", 123);
+ reporter->it_failed("my test & < > \\ \"", exception);
+
+ reporter->context_ended("my context & < > \\ \"");
+ reporter->test_run_complete();
+ });
+
+ it("outputs the escaped characters", [&](){
+ AssertThat(output(), Contains(
+ "<testsuite name=\"bandit\" tests=\"1\" errors=\"0\" failures=\"1\">\n"
+ "\t<testcase classname=\"my context &amp; &lt; &gt; &apos; &quot;\" name=\"my test &amp; &lt; &gt; &apos; &quot;\" time=\"0\">\n"
+ "\t\t<failure message=\"some_file:123: assertion failed &amp; &lt; &gt; &apos; &quot;\" />\n"
+ "\t</testcase>\n"
+ "</testsuite>\n"));
+ });
+
+ });
+
+ describe("a context with a skipped test", [&](){
+
+ before_each([&](){
+ reporter->test_run_starting();
+ reporter->context_starting("my context");
+
+ reporter->it_starting("my test");
+ reporter->it_succeeded("my test");
+ reporter->it_skip("my skipped test");
+
+ reporter->context_ended("my context");
+ reporter->test_run_complete();
+ });
+
+ it("outputs info about the skipped test", [&](){
+ AssertThat(output(), Contains(
+ "<testsuite name=\"bandit\" tests=\"1\" errors=\"0\" failures=\"0\" skipped=\"1\">\n"
+ "\t<testcase classname=\"my context\" name=\"my test\" time=\"0\">\n"
+ "\t</testcase>\n"
+ "\t<testcase classname=\"my context\" name=\"my skipped test\" time=\"0\">\n"
+ "\t\t<skipped />\n"
+ "\t</testcase>\n"
+ "</testsuite>\n"));
+ });
+
+ });
+
+ });
+
+});
diff --git a/vendor/bandit/specs/run.spec.cpp b/vendor/bandit/specs/run.spec.cpp
new file mode 100644
index 00000000..6e59bac7
--- /dev/null
+++ b/vendor/bandit/specs/run.spec.cpp
@@ -0,0 +1,77 @@
+#include <specs/specs.h>
+using namespace bandit::fakes;
+using namespace bandit::specs::util;
+namespace bd = bandit::detail;
+
+go_bandit([](){
+
+ describe("run:", [&](){
+ std::unique_ptr<bd::spec_registry> specs;
+ std::unique_ptr<argv_helper> argv;
+ fake_reporter_ptr reporter;
+ std::unique_ptr<bd::contextstack_t> context_stack;
+
+ auto call_run = [&]() -> int {
+ bd::options opt(argv->argc(), argv->argv());
+ return bandit::run(opt, *specs, *context_stack, *reporter);
+ };
+
+ before_each([&](){
+ specs = std::unique_ptr<bd::spec_registry>(new bd::spec_registry());
+
+ reporter = fake_reporter_ptr(new fake_reporter());
+
+ context_stack = std::unique_ptr<bd::contextstack_t>(new bd::contextstack_t());
+
+ const char* args[] = {"executable"};
+ argv = std::unique_ptr<argv_helper>(new argv_helper(1, args));
+ });
+
+ it("pushes the global context on the context stack", [&](){
+ call_run();
+ AssertThat(*context_stack, Is().OfLength(1));
+ });
+
+ describe("a successful test run", [&](){
+ int number_of_specs_called;
+
+ before_each([&](){
+ number_of_specs_called = 0;
+ specs->push_back([&](){ number_of_specs_called++; });
+ });
+
+ it("calls the context", [&](){
+ call_run();
+ AssertThat(number_of_specs_called, Equals(1));
+ });
+
+ it("tells reporter a test run is about to start", [&](){
+ call_run();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("test_run_starting"));
+ });
+
+ it("tells reporter a test run has completed", [&](){
+ call_run();
+ AssertThat(reporter->call_log(), Has().Exactly(1).EqualTo("test_run_complete"));
+ });
+
+ it("returns 0 as no specs failed", [&](){
+ AssertThat(call_run(), Equals(0));
+ });
+ });
+
+
+ describe("a failing test run", [&](){
+
+ before_each([&](){
+ reporter->set_test_run_status(false);
+ });
+
+ it("returns a non-zero error code", [&](){
+ AssertThat(call_run(), IsGreaterThan(0));
+ });
+
+ });
+ });
+
+});
diff --git a/vendor/bandit/specs/run_policies/bandit_run_policy.spec.cpp b/vendor/bandit/specs/run_policies/bandit_run_policy.spec.cpp
new file mode 100644
index 00000000..75f56bc6
--- /dev/null
+++ b/vendor/bandit/specs/run_policies/bandit_run_policy.spec.cpp
@@ -0,0 +1,250 @@
+#include <specs/specs.h>
+
+go_bandit([](){
+ namespace bd = bandit::detail;
+
+ describe("bandit run policy", [&](){
+ std::unique_ptr<bd::contextstack_t> contextstack;
+ std::unique_ptr<bd::context> global_context;
+ std::string only_pattern;
+ std::string skip_pattern;
+ bool break_on_failure;
+
+ auto create_policy = [&]() -> bd::bandit_run_policy {
+ return bd::bandit_run_policy(skip_pattern.c_str(), only_pattern.c_str(), break_on_failure);
+ };
+
+ before_each([&](){
+ contextstack = std::unique_ptr<bd::contextstack_t>(new bd::contextstack_t());
+ bool hard_skip = false;
+ global_context = std::unique_ptr<bd::context>(new bd::bandit_context("", hard_skip));
+ contextstack->push_back(global_context.get());
+ break_on_failure = false;
+ });
+
+ describe("neither skip nor only specified", [&](){
+ before_each([&](){
+ only_pattern = "";
+ skip_pattern = "";
+ });
+
+ it("always says run", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsTrue());
+ });
+
+ describe("with 'break-on-failure' set", [&](){
+
+ before_each([&](){
+ break_on_failure = true;
+ });
+
+ it("says run if no failure has been encountered", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsTrue());
+ });
+
+ it("says don't run if a failure has been encountered", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ policy.encountered_failure();
+ AssertThat(policy.should_run("it name", *contextstack), IsFalse());
+ });
+
+ });
+
+ describe("has context marked with 'hard_skip' in stack", [&](){
+ std::unique_ptr<bd::context> hard_skip_context;
+
+ before_each([&](){
+ bool hard_skip = true;
+ hard_skip_context = std::unique_ptr<bd::context>(new bd::bandit_context("always ignore", hard_skip));
+ contextstack->push_back(hard_skip_context.get());
+ });
+
+ it("never runs", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsFalse());
+ AssertThat(policy.should_run("it name matches 'skip'", *contextstack), IsFalse());
+ AssertThat(policy.should_run("it name matches 'only'", *contextstack), IsFalse());
+ });
+
+ });
+
+ });
+
+ describe("'skip' specified, 'only' unspecified", [&](){
+
+ before_each([&](){
+ only_pattern = "";
+ skip_pattern = "skip";
+ });
+
+ describe("current context matches 'skip'", [&](){
+ std::unique_ptr<bd::context> current_context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ current_context = std::unique_ptr<bd::context>(new bd::bandit_context("context matches 'skip'", hard_skip));
+ contextstack->push_back(current_context.get());
+ });
+
+ it("never runs", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsFalse());
+ });
+
+ });
+
+ describe("current context doesn't match 'skip'", [&](){
+ std::unique_ptr<bd::context> current_context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ current_context = std::unique_ptr<bd::context>(new bd::bandit_context("context doesn't match", hard_skip));
+ contextstack->push_back(current_context.get());
+ });
+
+ it("runs if spec's name doesn't match", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsTrue());
+ });
+
+ it("doesn't run if spec's name matches", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name matching 'skip'", *contextstack), IsFalse());
+ });
+
+ });
+
+ });
+
+ describe("'only' specified, 'skip' unspecified", [&](){
+
+ before_each([&](){
+ only_pattern = "only";
+ skip_pattern = "";
+ });
+
+ describe("current context matches 'only'", [&](){
+ std::unique_ptr<bd::context> current_context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ current_context = std::unique_ptr<bd::context>(new bd::bandit_context("context matches 'only'", hard_skip));
+ contextstack->push_back(current_context.get());
+ });
+
+ it("always runs", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsTrue());
+ });
+
+ });
+
+ describe("current context doesn't match 'only'", [&](){
+ std::unique_ptr<bd::context> current_context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ current_context = std::unique_ptr<bd::context>(new bd::bandit_context("context doesn't match", hard_skip));
+ contextstack->push_back(current_context.get());
+ });
+
+ it("doesn't run if spec's name doesn't match", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsFalse());
+ });
+
+ it("runs if spec's name matches", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name matching 'only'", *contextstack), IsTrue());
+ });
+
+ });
+
+ });
+
+ describe("'skip' specified, 'only' specified", [&](){
+
+ before_each([&](){
+ only_pattern = "only";
+ skip_pattern = "skip";
+ });
+
+ describe("current context matches 'skip'", [&](){
+ std::unique_ptr<bd::context> current_context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ current_context = std::unique_ptr<bd::context>(new bd::bandit_context("context matches 'skip'", hard_skip));
+ contextstack->push_back(current_context.get());
+ });
+
+ it("doesn't run if 'it' doesn't match 'only'", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsFalse());
+ });
+
+ it("runs if 'it' matches 'only'", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it matches 'only'", *contextstack), IsTrue());
+ });
+
+ });
+
+ describe("current context 'only'", [&](){
+ std::unique_ptr<bd::context> current_context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ current_context = std::unique_ptr<bd::context>(new bd::bandit_context("context matches 'only'", hard_skip));
+ contextstack->push_back(current_context.get());
+ });
+
+ it("runs if spec's name doesn't match anything", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsTrue());
+ });
+
+ it("doesn't run if spec's name matches 'skip'", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name matching 'skip'", *contextstack), IsFalse());
+ });
+
+ });
+
+ describe("has both 'only' and 'skip' in context stack", [&](){
+ std::unique_ptr<bd::context> current_context;
+ std::unique_ptr<bd::context> parent_context;
+
+ before_each([&](){
+ bool hard_skip = false;
+ current_context = std::unique_ptr<bd::context>(new bd::bandit_context("context matches 'only'", hard_skip));
+ parent_context = std::unique_ptr<bd::context>(new bd::bandit_context("context matches 'skip'", hard_skip));
+ contextstack->push_back(parent_context.get());
+ contextstack->push_back(current_context.get());
+ });
+
+ it("runs if spec's name doesn't match anything", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name", *contextstack), IsTrue());
+ });
+
+ it("doesn't run if spec's name matches 'skip'", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name matching 'skip'", *contextstack), IsFalse());
+ });
+ it("runs if spec's name matches 'only'", [&](){
+ bd::bandit_run_policy policy = create_policy();
+ AssertThat(policy.should_run("it name matching 'only'", *contextstack), IsTrue());
+ });
+
+ });
+
+ });
+
+
+ });
+
+});
+
diff --git a/vendor/bandit/specs/specs.h b/vendor/bandit/specs/specs.h
new file mode 100644
index 00000000..219e89ee
--- /dev/null
+++ b/vendor/bandit/specs/specs.h
@@ -0,0 +1,10 @@
+#ifndef BANDIT_SPECS
+#define BANDIT_SPECS
+
+#include <bandit/bandit.h>
+using namespace bandit;
+
+#include <specs/fakes/fakes.h>
+#include <specs/util/util.h>
+
+#endif
diff --git a/vendor/bandit/specs/synopsis.spec.cpp b/vendor/bandit/specs/synopsis.spec.cpp
new file mode 100644
index 00000000..3b717f75
--- /dev/null
+++ b/vendor/bandit/specs/synopsis.spec.cpp
@@ -0,0 +1,54 @@
+#include <specs/specs.h>
+
+go_bandit([](){
+ describe("my first spec", [&]() {
+ int a;
+
+ before_each([&](){
+ a = 99;
+ });
+
+ it("should be initialized", [&](){
+ AssertThat(a, Equals(99));
+ a = 102;
+ });
+
+ describe("nested spec", [&](){
+
+ before_each([&](){
+ a += 3;
+ });
+
+ it("should build on outer spec", [&](){
+ AssertThat(a, Equals(102));
+ a = 666;
+ });
+
+ it("should build on outer spec yet again", [&](){
+ AssertThat(a, Equals(102));
+ a = 667;
+ });
+
+ });
+
+ it("should be initialized before each it", [&](){
+ AssertThat(a, Equals(99));
+ });
+ });
+
+ describe("my second spec", [&](){
+ int b;
+
+ before_each([&](){
+ b = 22;
+ });
+
+ before_each([&](){
+ b += 3;
+ });
+
+ it("should be 25", [&](){
+ AssertThat(b, Equals(25));
+ });
+ });
+});
diff --git a/vendor/bandit/specs/util/argv_helper.h b/vendor/bandit/specs/util/argv_helper.h
new file mode 100644
index 00000000..dac26765
--- /dev/null
+++ b/vendor/bandit/specs/util/argv_helper.h
@@ -0,0 +1,62 @@
+#ifndef BANDIT_SPECS_ARGV_HELPER_H
+#define BANDIT_SPECS_ARGV_HELPER_H
+
+#include <string.h>
+
+namespace bandit { namespace specs { namespace util {
+
+ //
+ // main() is supposed to receive its arguments as a non const 'char* argv[]'.
+ // This is a pain to create for each test. It's a whole lot easier to create
+ // a 'const char* argv[]' construct.
+ //
+ // This class helps copy from 'const char**' to 'char**' and handle cleanup
+ // automatically.
+ //
+ struct argv_helper
+ {
+ argv_helper(int argc_a, const char* argv_a[])
+ : argc_(argc_a)
+ {
+ non_const_argv_ = new char*[argc_];
+ for(int i=0; i < argc_; i++)
+ {
+ std::string s(argv_a[i]);
+ non_const_argv_[i] = new char[s.size() + 1];
+ for(size_t c=0;c<s.size();c++)
+ {
+ non_const_argv_[i][c] = s[c];
+ }
+ non_const_argv_[i][s.size()] = 0;
+ }
+ }
+
+
+
+ ~argv_helper()
+ {
+ for(int i=0; i < argc_; i++)
+ {
+ delete[] non_const_argv_[i];
+ }
+
+ delete[] non_const_argv_;
+ }
+
+ char** argv()
+ {
+ return non_const_argv_;
+ }
+
+ int argc()
+ {
+ return argc_;
+ }
+
+ private:
+ int argc_;
+ char** non_const_argv_;
+ };
+
+}}}
+#endif
diff --git a/vendor/bandit/specs/util/util.h b/vendor/bandit/specs/util/util.h
new file mode 100644
index 00000000..7ed17dd8
--- /dev/null
+++ b/vendor/bandit/specs/util/util.h
@@ -0,0 +1,6 @@
+#ifndef BANDIT_SPECS_UTIL_H
+#define BANDIT_SPECS_UTIL_H
+
+#include "argv_helper.h"
+
+#endif