Specs
Beautiful C++ Test Framework
Loading...
Searching...
No Matches
Entrypoint.h
Go to the documentation of this file.
1#pragma once
2
16
17#include <cxxopts.hpp>
18#include <filesystem>
19#include <iostream>
20
21// TODO: add a standard options object to API.h to be explicit about all of the BUILT-IN OPTIONS
22// which will let us more easily pass things like a LIST of tags to include or exclude ETC
23//
24// And the options like --name should ALSO support a LIST (for OR matching in that case)
25//
26// We can ALSO provide a way to specify a custom options object to the runner, which will let
27// folks pass data along using our Data collection object (but it only supports simple values)
28
29namespace SpecsCpp {
30
31 // TODO: this should implement an interface
32 class Entrypoint {
33 int _returnCode = 0;
34 int _totalTests = 0;
35
36 // SpecRunOptions _options;
37 SpecEnvironment _specs;
38 SpecSerialRunner _runner;
39 SpecDebugReporter _reporter;
40 SpecReporterCollection _reporters;
41 SpecDataValueCollection _runnerOptions;
42 LibraryLoader _LibraryLoader{&_specs};
43
44 ExceptionHandlers::CStringExceptionHandler _cStringExceptionHandler;
45 ExceptionHandlers::StdExceptionExceptionHandler _stdExceptionExceptionHandler;
46
47 void on_suite_complete(ISpecSuiteRunResult* result) {
48 _returnCode = result->failed() > 0 ? 1 : 0;
49 _totalTests =
50 result->passed() + result->failed() + result->not_run() + result->timed_out();
51 }
52
53 FunctionPointer<void(ISpecSuiteRunResult*)> _onSuiteComplete =
54 function_pointer(this, &Entrypoint::on_suite_complete);
55
56 public:
57 int main(int argc, char** argv) {
58 cxxopts::Options options("Specs.cpp", "Specs.cpp command line options");
59 options.allow_unrecognised_options();
60
61 // TODO: option to specify / customize the reporters used
62 // TODO: option to specify / customize the runner used
63 options.add_options()
64 // ("n,name", "Filter name of test/group to run", cxxopts::value<std::string>())
65 // ("s,spec", "Filter name of test to run", cxxopts::value<std::string>())
66 // ("g,group", "Filter name of group to run", cxxopts::value<std::string>())
67 // ("r,pattern", "Regex pattern filter of test/group to run",
68 // cxxopts::value<std::string>())
69 // ("spec-pattern", "Regex pattern filter of test to run",
70 // cxxopts::value<std::string>())
71 // ("group-pattern", "Regex pattern filter of group to run",
72 // cxxopts::value<std::string>())
73 // ("l,list", "List all tests and groups",
74 // cxxopts::value<bool>()->default_value("false"))
75 // ("dll,so", "Load tests from shared library (--dll,--so)",
76 // cxxopts::value<std::vector<std::string>>())
77 // ("i,tag", "(TODO) Tag name of test to include",
78 // cxxopts::value<std::vector<std::string>>())
79 // ("e,exclude-tag", "(TODO) Tag name of test to exclude",
80 // cxxopts::value<std::vector<std::string>>())
81 // ("t,timeout", "Timeout in milliseconds for each test", cxxopts::value<int>())
82 ("h,help", "Print usage");
83
84 auto result = options.parse(argc, argv);
85 if (result.count("help")) {
86 std::cout << options.help() << std::endl;
87 return 0;
88 }
89
90 // if (result.count("name"))
91 // _runnerOptions.add(SpecDataValue::create_string(
92 // ISpecRunner::DESCRIPTION_FILTER_OPTION_KEY,
93 // result["name"].as<std::string>().c_str()
94 // ));
95 // if (result.count("spec"))
96 // _runnerOptions.add(SpecDataValue::create_string(
97 // ISpecRunner::SPEC_DESCRIPTION_FILTER_OPTION_KEY,
98 // result["spec"].as<std::string>().c_str()
99 // ));
100 // if (result.count("group"))
101 // _runnerOptions.add(SpecDataValue::create_string(
102 // ISpecRunner::GROUP_DESCRIPTION_FILTER_OPTION_KEY,
103 // result["group"].as<std::string>().c_str()
104 // ));
105 // if (result.count("pattern"))
106 // _runnerOptions.add(SpecDataValue::create_string(
107 // ISpecRunner::DESCRIPTION_REGEX_FILTER_OPTION_KEY,
108 // result["pattern"].as<std::string>().c_str()
109 // ));
110 // if (result.count("spec-pattern"))
111 // _runnerOptions.add(SpecDataValue::create_string(
112 // ISpecRunner::SPEC_DESCRIPTION_REGEX_FILTER_OPTION_KEY,
113 // result["spec-pattern"].as<std::string>().c_str()
114 // ));
115 // if (result.count("group-pattern"))
116 // _runnerOptions.add(SpecDataValue::create_string(
117 // ISpecRunner::GROUP_DESCRIPTION_REGEX_FILTER_OPTION_KEY,
118 // result["group-pattern"].as<std::string>().c_str()
119 // ));
120 // if (result.count("list"))
121 // _runnerOptions.add(SpecDataValue::create_bool(
122 // ISpecRunner::LIST_TEST_NAMES_OPTION_KEY, result["list"].as<bool>()
123 // ));
124 // if (result.count("timeout"))
125 // _runnerOptions.add(SpecDataValue::create_int(
126 // ISpecRunner::DEFAULT_TIMEOUT_MS_OPTION_KEY, result["timeout"].as<int>()
127 // ));
128
129 if (result.unmatched().size() > 0) {
130 std::cout << "Unrecognized options:" << std::endl;
131 for (auto& option : result.unmatched()) std::cout << " " << option << std::endl;
132 return 1;
133 }
134
135 global_spec_environment().set(&_specs);
136 _specs.root_group()->merge(GlobalSpecGroup::instance().root());
137 _specs.local_exception_handlers()->register_exception_handler(&_cStringExceptionHandler
138 );
140 &_stdExceptionExceptionHandler
141 );
143
144 // if (result.count("dll")) {
145 // for (auto& dll : result["dll"].as<std::vector<std::string>>()) {
146 // if (!std::filesystem::exists(dll)) {
147 // std::cout << "Specs.cpp: Error: Spec dll/so file not found: " << dll
148 // << std::endl;
149 // return 1;
150 // }
151 // if (auto* dllRootSpecGroup = _LibraryLoader.load(dll)) {
152 // _specs.root_group()->merge(dllRootSpecGroup);
153 // } else {
154 // std::cout << "Specs.cpp: Error: Failed to load group from dll/so file: "
155 // << dll << std::endl;
156 // return 1;
157 // }
158 // }
159 // }
160
161 _reporters.add("debug", &_reporter);
162 _runner.run(_specs.root_group(), &_reporters, nullptr, &_onSuiteComplete);
163
164 if (_totalTests == 0) {
165 std::cout << "No tests found.\n" << std::endl;
166 std::cout << options.help() << std::endl;
167 return 0;
168 }
169
170 return _returnCode;
171 }
172 };
173}
int main(int argc, char **argv)
Definition Entrypoint.h:57
static GlobalSpecCodeBlocks & instance()
void set(ISpecEnvironment *environment)
static GlobalSpecGroup & instance()
ISpecGroup * root_group() const override
ILocalSpecExceptionHandlerCollection * local_exception_handlers() const override
void add(const char *name, ISpecReporter *reporter) override
void run(ISpecGroup *group, ISpecReporterCollection *reporters, ISpecRunOptions *options, ISpecSuiteRunResultCallbackFn *callback) override
Definition API.h:3
GlobalSpecEnvironment & global_spec_environment()
virtual void register_exception_handler(ILocalSpecExceptionHandler *)=0
virtual void merge(ISpecGroup *)=0
virtual std::uint32_t not_run() const =0
virtual std::uint32_t failed() const =0
virtual std::uint32_t timed_out() const =0
virtual std::uint32_t passed() const =0