Skip to content

Commit fb239fb

Browse files
committed
Separate runnable.hpp and general header cleanup
1 parent a7b1bf5 commit fb239fb

28 files changed

+450
-327
lines changed

examples/sample/example_spec.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <list>
44
#include "cppspec.hpp"
55

6-
76
describe bool_spec("Some Tests", $ {
87
context("true is", _ {
98
it("true", _ {
@@ -30,7 +29,7 @@ describe bool_spec("Some Tests", $ {
3029
});
3130

3231
explain("0 is", _ {
33-
using namespace Matchers;
32+
using namespace CppSpec::Matchers;
3433
it("between -1 and 1 (exclusive)", _ {
3534
expect(0).to_be_between(-1, 1, RangeMode::exclusive);
3635
});
@@ -191,7 +190,7 @@ describe list_spec("A list spec", $ {
191190
/* Here is the declaration of fabs description defined in an other file (fabs_spec.c in this sample)*/
192191
int main(){
193192
bool r = true;
194-
PrettyPrinter printer = Printer::verbose;
193+
auto printer = CppSpec::Printer::verbose;
195194
r &= bool_spec.run(printer);
196195
r &= abs_spec.run(printer);
197196
r &= strcmp_spec.run(printer);

include/child.hpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#ifndef CPPSPEC_CHILD_HPP
2+
#define CPPSPEC_CHILD_HPP
3+
#include <string>
4+
5+
namespace CppSpec {
6+
7+
struct BasePrinter;
8+
9+
/**
10+
* @brief Base class for all objects in the execution tree.
11+
*
12+
* A base class for all objects that comprise some abstract structure
13+
* with a nesting concept. Used to propogate ('pass') failures from leaf
14+
* to root without exceptions (and/or code-jumping), thus allowing
15+
* execution to continue virtually uninterrupted.
16+
*/
17+
class Child {
18+
// The parent of this child
19+
// We use a raw pointer here instead of the safer std::shared_ptr
20+
// due to the way that tests are inherently constructed
21+
// (`describe some_spec("a test", $ { ... });`). In order to use
22+
// a shared pointer, each object that is set as the parent must be
23+
// contained in a shared pointer. As tests are created by `describe ...`,
24+
// it is not wrapped by a shared pointer. Attempting to create this shared
25+
// pointer at some later time doesn't work, as it results in trying to delete
26+
// the current object `this` once the pointer goes out of scope.
27+
// Since children are always destroyed before their parents, this isn't a
28+
// problem anyways. In addition, any structures that are children are
29+
// allocated on the stack for speed reasons.
30+
Child *parent = nullptr;
31+
32+
// Represents whether the Child is healthy (has not failed).
33+
// A Child is healthy if and only if all of its children are healthy.
34+
// All instances of Child start out healthy.
35+
bool status = true;
36+
37+
BasePrinter *printer = nullptr;
38+
39+
public:
40+
// Default constructor/desctructor
41+
Child() = default;
42+
virtual ~Child() = default;
43+
44+
// Move constructor/operator
45+
Child(Child &&) = default;
46+
Child &operator=(Child &&) = default;
47+
48+
// Copy constructor/operator
49+
Child(const Child &) = default;
50+
Child &operator=(const Child &) = default;
51+
52+
// Custom constructors
53+
Child(Child &parent) : parent(&parent){};
54+
Child(Child *parent) : parent(parent){};
55+
Child(const Child *parent) : parent(const_cast<Child *>(parent)){};
56+
57+
/*--------- Parent helper functions -------------*/
58+
59+
/** @brief Check to see if the Child has a parent. */
60+
bool has_parent() { return parent != nullptr; }
61+
62+
/** @brief Get the Child's parent. */
63+
Child *get_parent() { return parent; }
64+
const Child *get_parent() const { return const_cast<Child *>(parent); }
65+
66+
/** @brief Set the Child's parent */
67+
void set_parent(Child *parent) { this->parent = parent; }
68+
69+
/*--------- Printer helper functions -------------*/
70+
const bool has_printer(); // Check to see if the tree has a printer
71+
BasePrinter &get_printer(); // Get the printer from the tree
72+
void set_printer(BasePrinter &printer) { this->printer = &printer; }
73+
74+
/*--------- Primary member functions -------------*/
75+
76+
/** @brief Get the status of the object (success/failure) */
77+
bool get_status() { return this->status; }
78+
79+
void failed(); // Report failure to the object.
80+
std::string padding(); // Calculate the padding for printing this object
81+
};
82+
83+
/*>>>>>>>>>>>>>>>>>>>> Child IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<*/
84+
85+
/**
86+
* @brief Report failure to the object.
87+
*
88+
* This is propogated up the parent/child tree, so that when a child object
89+
* fails, the parent object is immediately updated to reflect that as well.
90+
*/
91+
void Child::failed() {
92+
this->status = false;
93+
// propogates the failure up the tree
94+
if (has_parent()) this->get_parent()->failed();
95+
}
96+
97+
/**
98+
* @brief Get the padding (indentation) of the current object.
99+
* @return A string of spaces for use in pretty-printing.
100+
*/
101+
std::string Child::padding() {
102+
return has_parent() ? get_parent()->padding() + " " : "";
103+
}
104+
105+
const bool Child::has_printer() {
106+
if (this->printer != nullptr) return true;
107+
if (parent == nullptr) return false; // base case;
108+
return parent->has_printer();
109+
}
110+
111+
BasePrinter &Child::get_printer() {
112+
if (this->printer != nullptr) return *printer;
113+
if (parent == nullptr) throw "Couldn't get printer!"; // base case;
114+
return parent->get_printer();
115+
}
116+
117+
} // ::CppSpec
118+
#endif // CPPSPEC_CHILD_HPP

include/class_description.hpp

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
#ifndef CLASS_DESCRIPTION_H
2-
#define CLASS_DESCRIPTION_H
1+
#ifndef CPPSPEC_CLASS_DESCRIPTION_HPP
2+
#define CPPSPEC_CLASS_DESCRIPTION_HPP
33
#include "description.hpp"
44

5+
namespace CppSpec {
6+
57
/**
68
* @brief A Description with a defined subject
79
*
@@ -15,7 +17,7 @@
1517
*/
1618
template <class T>
1719
class ClassDescription : public Description {
18-
typedef std::function<void(ClassDescription<T>&)> block_t;
20+
typedef std::function<void(ClassDescription<T> &)> block_t;
1921
block_t body;
2022
bool first;
2123
std::string type = "";
@@ -46,13 +48,13 @@ class ClassDescription : public Description {
4648
ClassDescription(std::string descr, T subject, block_t body)
4749
: Description(descr), body(body), subject(subject){};
4850

49-
ClassDescription(T& subject, block_t body)
51+
ClassDescription(T &subject, block_t body)
5052
: Description(Pretty::to_word(subject)),
5153
body(body),
5254
type(" : " + Util::demangle(typeid(T).name())),
5355
subject(subject){};
5456

55-
ClassDescription(std::string descr, T& subject, block_t body)
57+
ClassDescription(std::string descr, T &subject, block_t body)
5658
: Description(descr), body(body), subject(subject){};
5759

5860
template <typename U>
@@ -68,16 +70,16 @@ class ClassDescription : public Description {
6870
block_t body)
6971
: Description(descr), body(body), subject(T(init_list)){};
7072

71-
ClassDescription<T>(Description& d) : Description(d){};
73+
ClassDescription<T>(Description &d) : Description(d){};
7274

7375
const bool has_subject = true;
7476

75-
Result it(std::string descr, std::function<void(ItCd<T>&)> body);
76-
Result it(std::function<void(ItCd<T>&)> body);
77+
Result it(std::string descr, std::function<void(ItCd<T> &)> body);
78+
Result it(std::function<void(ItCd<T> &)> body);
7779
Result context(T subject, block_t body);
78-
Result context(T& subject, block_t body);
80+
Result context(T &subject, block_t body);
7981
Result context(block_t body);
80-
Result run(BasePrinter& printer) override;
82+
Result run(BasePrinter &printer) override;
8183
virtual std::string get_descr() override;
8284
virtual const std::string get_descr() const override;
8385
};
@@ -87,7 +89,7 @@ using ClassContext = ClassDescription<T>;
8789

8890
template <class T>
8991
Result ClassDescription<T>::context(
90-
T subject, std::function<void(ClassDescription&)> body) {
92+
T subject, std::function<void(ClassDescription &)> body) {
9193
ClassContext<T> context(subject, body);
9294
context.set_parent(this);
9395
context.before_eaches = this->before_eaches;
@@ -97,13 +99,13 @@ Result ClassDescription<T>::context(
9799

98100
template <class T>
99101
Result ClassDescription<T>::context(
100-
T& subject, std::function<void(ClassDescription&)> body) {
102+
T &subject, std::function<void(ClassDescription &)> body) {
101103
return context(subject, body);
102104
}
103105

104106
template <class T>
105107
Result ClassDescription<T>::context(
106-
std::function<void(ClassDescription&)> body) {
108+
std::function<void(ClassDescription &)> body) {
107109
ClassContext<T> context(body);
108110
context.set_parent(this);
109111
context.before_eaches = this->before_eaches;
@@ -113,7 +115,7 @@ Result ClassDescription<T>::context(
113115

114116
template <class T>
115117
Result Description::context(T subject,
116-
std::function<void(ClassDescription<T>&)> body) {
118+
std::function<void(ClassDescription<T> &)> body) {
117119
ClassContext<T> context(body);
118120
context.subject = subject;
119121
context.set_parent(this);
@@ -130,7 +132,7 @@ Result Description::context(T subject,
130132

131133
template <class T, typename U>
132134
Result Description::context(std::initializer_list<U> init_list,
133-
std::function<void(ClassDescription<T>&)> body) {
135+
std::function<void(ClassDescription<T> &)> body) {
134136
ClassContext<T> context(T(init_list), body);
135137
context.set_parent(this);
136138
context.before_eaches = this->before_eaches;
@@ -161,7 +163,7 @@ Result Description::context(std::initializer_list<U> init_list,
161163
*/
162164
template <class T>
163165
Result ClassDescription<T>::it(std::string name,
164-
std::function<void(ItCd<T>&)> body) {
166+
std::function<void(ItCd<T> &)> body) {
165167
ItCd<T> it(*this, this->subject, name, body);
166168
Result result = it.run(this->get_printer());
167169
exec_after_eaches();
@@ -191,7 +193,7 @@ Result ClassDescription<T>::it(std::string name,
191193
* @return the result of the test
192194
*/
193195
template <class T>
194-
Result ClassDescription<T>::it(std::function<void(ItCd<T>&)> body) {
196+
Result ClassDescription<T>::it(std::function<void(ItCd<T> &)> body) {
195197
ItCd<T> it(*this, this->subject, body);
196198
Result result = it.run(this->get_printer());
197199
exec_after_eaches();
@@ -200,7 +202,7 @@ Result ClassDescription<T>::it(std::function<void(ItCd<T>&)> body) {
200202
}
201203

202204
template <class T>
203-
Result ClassDescription<T>::run(BasePrinter& printer) {
205+
Result ClassDescription<T>::run(BasePrinter &printer) {
204206
if (not this->has_printer()) this->set_printer(printer);
205207
printer.print(*this);
206208
body(*this);
@@ -219,7 +221,7 @@ std::string ClassDescription<T>::get_descr() {
219221

220222
template <class T>
221223
const std::string ClassDescription<T>::get_descr() const {
222-
if (const_cast<ClassDescription<T>*>(this)->get_printer().mode ==
224+
if (const_cast<ClassDescription<T> *>(this)->get_printer().mode ==
223225
BasePrinter::Mode::TAP) {
224226
return descr;
225227
} else {
@@ -229,13 +231,13 @@ const std::string ClassDescription<T>::get_descr() const {
229231

230232
template <class T>
231233
Expectations::Expectation<T> ItCd<T>::is_expected() {
232-
auto cd = static_cast<ClassDescription<T>*>(this->get_parent());
234+
auto cd = static_cast<ClassDescription<T> *>(this->get_parent());
233235
Expectations::Expectation<T> expectation(*this, cd->subject);
234236
return expectation;
235237
}
236238

237239
template <class T>
238-
Result ItCd<T>::run(BasePrinter& printer) {
240+
Result ItCd<T>::run(BasePrinter &printer) {
239241
if (!this->needs_descr() && printer.mode == BasePrinter::Mode::verbose) {
240242
printer.print(*this);
241243
}
@@ -247,9 +249,10 @@ Result ItCd<T>::run(BasePrinter& printer) {
247249
printer.print(*this);
248250
}
249251

250-
auto cd = static_cast<ClassDescription<T>*>(this->get_parent());
252+
auto cd = static_cast<ClassDescription<T> *>(this->get_parent());
251253
cd->reset_lets();
252254
return this->get_status() ? Result::success : Result::failure;
253255
}
254256

255-
#endif /* CLASS_DESCRIPTION_H */
257+
} // ::CppSpec
258+
#endif // CPPSPEC_CLASS_DESCRIPTION_HPP

include/cppspec.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @file
33
* @brief The core header file for Cppspec
44
*/
5+
56
#include "printer.hpp"
67

78
#define _ [=](auto &self) mutable
@@ -21,7 +22,7 @@
2122
auto name = self.make_let(#name, body); \
2223
self.let(#name, name);
2324

24-
typedef Description describe;
25+
typedef CppSpec::Description describe;
2526

2627
template <class T>
27-
using describe_a = ClassDescription<T>;
28+
using describe_a = CppSpec::ClassDescription<T>;

include/description.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
* @file
33
* @brief Defines the Description class and associated functions
44
*/
5-
#ifndef DESCRIPTION_H
6-
#define DESCRIPTION_H
5+
#ifndef CPPSPEC_DESCRIPTION_HPP
6+
#define CPPSPEC_DESCRIPTION_HPP
77
#include <queue>
88
#include <unordered_map>
99
#include "it.hpp"
1010

11+
namespace CppSpec {
12+
1113
template <class T>
1214
class ClassDescription;
1315

@@ -144,6 +146,13 @@ void Description::exec_after_eaches() {
144146
for (rule_block_t b : after_eaches) b();
145147
}
146148

149+
/**
150+
* @brief Object generator for Let.
151+
*
152+
* @param body the body of the let statement
153+
*
154+
* @return a new Let object
155+
*/
147156
template <typename T>
148157
auto Description::make_let(std::string name, T body) -> Let<decltype(body())> {
149158
return Let<decltype(body())>(*this, name, body);
@@ -216,4 +225,5 @@ Result ItD::run(BasePrinter &printer) {
216225
return this->get_status() ? Result::success : Result::failure;
217226
}
218227

219-
#endif /* DESCRIPTION_H */
228+
} // ::CppSpec
229+
#endif // CPPSPEC_DESCRIPTION_HPP

0 commit comments

Comments
 (0)