Echo Writes Code

suite.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "crucible/test/suite.inl"

#include <memory>

namespace crucible::test
{
  struct Suite_Data {};

  Suite::Suite(std::unique_ptr<Suite_Data> data) :
    my_data { std::move(data) }
  {}

  auto Suite::set_name(std::string const &name) -> void
  {
    my_name = name;
  }

  auto Suite::set_group_filter(std::set<core::String> const &group_filter) -> void
  {
    my_group_filter = group_filter;
  }

  auto Suite::add_scenario(std::string const &group, std::string const &name, Scenario_Function const &function) -> void
  {
    auto emplace_result { my_scenarios_by_group.emplace(group, make_heap_buffer<Scenario>()) };
    auto &iterator { emplace_result.first };
    auto &scenario_list { iterator->second };
    scenario_list.push(group, name, function);
  }

  auto Suite::execute(Reporter &reporter) -> bool
  {
    if (my_scenarios_by_group.empty()) {
      reporter.handle_empty_suite(my_name);
      return true;
    }

    reporter.handle_suite_start(my_name);
    execute_scenarios(reporter);
    reporter.handle_suite_end(my_pass_count, my_fail_count, my_scenario_count, my_fixture_count);

    return my_fail_count == 0;
  }

  auto Suite::execute_scenarios(Reporter &reporter) -> void
  {
    for (auto &pair : my_scenarios_by_group) {
      auto const &group = pair.first;

      auto const execute_scenario {
        [&group, &reporter, this](Scenario const &scenario) {
          execute_fixtures_with_group<Before_Each>(group, reporter);
          reporter.handle_scenario_start(scenario);

          auto const outcome { scenario.execute() };

          reporter.handle_scenario_end(scenario, outcome);
          execute_fixtures_with_group<After_Each>(group, reporter);

          ++my_scenario_count;

          if (outcome.passed()) {
            ++my_pass_count;
            return;
          }

          ++my_fail_count;
        }
      };

      auto const hack { make_string_from_char_array(group.data(), group.size()) };

      bool const do_filtering { !my_group_filter.empty() };
      bool const is_filtered_out { my_group_filter.find(hack) == my_group_filter.end() };

      if (do_filtering && is_filtered_out) {
        continue;
      }

      execute_fixtures_with_group<Before_All>(group, reporter);
      reporter.handle_group_start(group);

      auto &scenario_list { pair.second };

      iterate(scenario_list)
        .consume(execute_scenario);

      reporter.handle_group_end(group);
      execute_fixtures_with_group<After_All>(group, reporter);
    }
  }

  auto suite() -> Suite &
  {
    static Suite instance { std::make_unique<Suite_Data>() };
    return instance;
  }

  Scenario_Registrar::Scenario_Registrar(std::string const &group, std::string const &name, Scenario_Function const &test)
  {
    suite().add_scenario(group, name, test);
  }
}