#ifndef BANDIT_GRAMMAR_H #define BANDIT_GRAMMAR_H namespace bandit { inline void describe(const char* desc, detail::voidfunc_t func, detail::listener& listener, detail::contextstack_t& context_stack, bool hard_skip = false) { listener.context_starting(desc); context_stack.back()->execution_is_starting(); detail::bandit_context ctxt(desc, hard_skip); context_stack.push_back(&ctxt); try { func(); } catch(const bandit::detail::test_run_error& error) { listener.test_run_error(desc, error); } context_stack.pop_back(); listener.context_ended(desc); } inline void describe(const char* desc, detail::voidfunc_t func) { describe(desc, func, detail::registered_listener(), detail::context_stack()); } inline void describe_skip(const char* desc, detail::voidfunc_t func, detail::listener& listener, detail::contextstack_t& context_stack) { bool skip = true; describe(desc, func, listener, context_stack, skip); } inline void describe_skip(const char* desc, detail::voidfunc_t func) { describe_skip(desc, func, detail::registered_listener(), detail::context_stack()); } inline void xdescribe(const char* desc, detail::voidfunc_t func, detail::listener& listener=detail::registered_listener(), detail::contextstack_t& context_stack=detail::context_stack()) { describe_skip(desc, func, listener, context_stack); } inline void before_each(detail::voidfunc_t func, detail::contextstack_t& context_stack) { context_stack.back()->register_before_each(func); } inline void before_each(detail::voidfunc_t func) { before_each(func, detail::context_stack()); } inline void after_each(detail::voidfunc_t func, detail::contextstack_t& context_stack) { context_stack.back()->register_after_each(func); } inline void after_each(detail::voidfunc_t func) { after_each(func, detail::context_stack()); } inline void it_skip(const char* desc, detail::voidfunc_t, detail::listener& listener) { listener.it_skip(desc); } inline void it_skip(const char* desc, detail::voidfunc_t func) { it_skip(desc, func, detail::registered_listener()); } inline void xit(const char* desc, detail::voidfunc_t func, detail::listener& listener=detail::registered_listener()) { it_skip(desc, func, listener); } inline void it(const char* desc, detail::voidfunc_t func, detail::listener& listener, detail::contextstack_t& context_stack, bandit::adapters::assertion_adapter& assertion_adapter, detail::run_policy& run_policy) { if(!run_policy.should_run(desc, context_stack)) { it_skip(desc, func, listener); return; } listener.it_starting(desc); context_stack.back()->execution_is_starting(); auto run_before_eaches = [&](){ for_each(context_stack.begin(), context_stack.end(), [](detail::context* ctxt){ ctxt->run_before_eaches(); }); }; auto run_after_eaches = [&](){ for_each(context_stack.begin(), context_stack.end(), [](detail::context* ctxt){ ctxt->run_after_eaches(); }); }; bool we_have_been_successful_so_far = false; try { assertion_adapter.adapt_exceptions([&](){ run_before_eaches(); func(); we_have_been_successful_so_far = true; }); } catch(const bandit::detail::assertion_exception& ex) { listener.it_failed(desc, ex); run_policy.encountered_failure(); } catch(const std::exception& ex) { std::string err = std::string("exception: ") + ex.what(); listener.it_failed(desc, bandit::detail::assertion_exception(err)); run_policy.encountered_failure(); } catch(...) { listener.it_unknown_error(desc); run_policy.encountered_failure(); } try { assertion_adapter.adapt_exceptions([&](){ run_after_eaches(); if(we_have_been_successful_so_far) { listener.it_succeeded(desc); } }); } catch(const bandit::detail::assertion_exception& ex) { listener.it_failed(desc, ex); run_policy.encountered_failure(); } catch(const std::exception& ex) { std::string err = std::string("exception: ") + ex.what(); listener.it_failed(desc, bandit::detail::assertion_exception(err)); run_policy.encountered_failure(); } catch(...) { listener.it_unknown_error(desc); run_policy.encountered_failure(); } } inline void it(const char* desc, detail::voidfunc_t func) { it(desc, func, detail::registered_listener(), detail::context_stack(), detail::registered_adapter(), detail::registered_run_policy()); } } #endif