Skip to content

Commit 87ff318

Browse files
committed
API adjustments and documentation
1 parent 1506371 commit 87ff318

File tree

8 files changed

+126
-100
lines changed

8 files changed

+126
-100
lines changed

include/child.hpp

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,11 @@ class Child {
5858
Child &operator=(Child &&) = default;
5959

6060
// Copy constructor/operator
61+
Child(const Child &) = default;
6162
Child &operator=(const Child &) = default;
6263

6364
// Custom constructors
64-
explicit Child(Child &parent) noexcept : parent(&parent) {}
65-
explicit Child(const Child &parent) noexcept
66-
: parent(&const_cast<Child &>(parent)) {}
67-
explicit Child(Child *parent) noexcept : parent(parent) {}
68-
explicit Child(const Child *parent) noexcept
69-
: parent(const_cast<Child *>(parent)) {}
65+
static Child of(const Child& parent) noexcept { return Child().set_parent(&parent); }
7066

7167
/*--------- Parent helper functions -------------*/
7268

@@ -76,52 +72,42 @@ class Child {
7672

7773
// TODO: Look in to making these references instead of pointer returns
7874
/** @brief Get the Child's parent. */
79-
Child *get_parent() noexcept { return parent; }
80-
const Child *get_parent() const noexcept {
81-
return const_cast<Child *>(parent);
82-
}
83-
84-
template <class C>
85-
C get_parent_as() noexcept {
86-
return static_cast<C>(get_parent());
87-
}
75+
Child *get_parent() const noexcept { return parent; }
8876

8977
template <class C>
9078
C get_parent_as() const noexcept {
9179
return static_cast<C>(get_parent());
9280
}
9381

9482
/** @brief Set the Child's parent */
95-
void set_parent(Child *parent) noexcept { this->parent = parent; }
96-
void set_parent(const Child *parent) noexcept {
83+
Child set_parent(Child *parent) noexcept { this->parent = parent; return *this; }
84+
Child& set_parent(const Child *parent) noexcept {
9785
this->parent = const_cast<Child *>(parent);
86+
return *this;
9887
}
9988

10089
/*--------- Formatter helper functions -----------*/
10190
// Check to see if the tree has a printer
102-
const bool has_formatter() noexcept;
91+
const bool has_formatter() const noexcept;
10392

10493
// Get the printer from the tree
105-
Formatters::BaseFormatter &get_formatter() noexcept;
94+
Formatters::BaseFormatter &get_formatter() const noexcept;
10695

107-
void set_printer(const Formatters::BaseFormatter &formatter) {
96+
void set_formatter(const Formatters::BaseFormatter &formatter) {
10897
this->formatter = &const_cast<Formatters::BaseFormatter &>(formatter);
10998
}
11099

111100
/*--------- Primary member functions -------------*/
112101

113102
/** @brief Get the status of the object (success/failure) */
114-
const bool get_status() noexcept { return this->status; }
115103
const bool get_status() const noexcept { return this->status; }
116-
117104
void failed() noexcept; // Report failure to the object.
118105

119106
// Calculate the padding for printing this object
120-
std::string padding() noexcept;
121107
std::string padding() const noexcept;
122108
};
123109

124-
/*>>>>>>>>>>>>>>>>>>>> Child IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<*/
110+
/*>>>>>>>>>>>>>>>>>>>> Child <<<<<<<<<<<<<<<<<<<<<<<<<*/
125111

126112
/**
127113
* @brief Report failure to the object.
@@ -139,21 +125,17 @@ inline void Child::failed() noexcept {
139125
* @brief Generate padding (indentation) fore the current object.
140126
* @return A string of spaces for use in pretty-printing.
141127
*/
142-
inline std::string Child::padding() noexcept {
143-
return this->has_parent() ? this->get_parent()->padding() + " " : "";
144-
}
145-
146128
inline std::string Child::padding() const noexcept {
147129
return this->has_parent() ? this->get_parent()->padding() + " " : "";
148130
}
149131

150-
inline const bool Child::has_formatter() noexcept {
132+
inline const bool Child::has_formatter() const noexcept {
151133
if (this->formatter != nullptr) return true;
152134
if (!this->has_parent()) return false; // base case;
153135
return parent->has_formatter();
154136
}
155137

156-
inline Formatters::BaseFormatter &Child::get_formatter() noexcept {
138+
inline Formatters::BaseFormatter &Child::get_formatter() const noexcept {
157139
if (this->formatter) return *formatter;
158140
if (!this->has_parent()) std::terminate();
159141
return parent->get_formatter();

include/class_description.hpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class ClassDescription : public Description {
2525
std::string type = "";
2626

2727
public:
28+
const bool has_subject = true;
2829
T subject; // subject field public for usage in `expect([self.]subject)`
2930

3031
// Constructor
@@ -69,10 +70,6 @@ class ClassDescription : public Description {
6970
Block block)
7071
: Description(description), block(block), subject(T(init_list)) {}
7172

72-
ClassDescription<T>(Description &d) : Description(d) {}
73-
74-
const bool has_subject = true;
75-
7673
Result it(std::string description, std::function<void(ItCD<T> &)> block);
7774
Result it(std::function<void(ItCD<T> &)> block);
7875
/** @brief an alias for it */
@@ -99,11 +96,7 @@ class ClassDescription : public Description {
9996

10097
Result run(Formatters::BaseFormatter &printer) override;
10198

102-
// std::string get_descr() noexcept override { return description; }
103-
// const std::string get_descr() const noexcept override { return
104-
// description; }
105-
std::string get_subject_type() noexcept override { return type; }
106-
const std::string get_subject_type() const noexcept override { return type; }
99+
std::string get_subject_type() const noexcept override { return type; }
107100
};
108101

109102
template <class T>
@@ -246,7 +239,7 @@ Result ClassDescription<T>::it(std::function<void(ItCD<T> &)> block) {
246239

247240
template <class T>
248241
Result ClassDescription<T>::run(Formatters::BaseFormatter &printer) {
249-
if (not this->has_formatter()) this->set_printer(printer);
242+
if (not this->has_formatter()) this->set_formatter(printer);
250243
printer.format(*this);
251244
this->block(*this);
252245
for (const auto &a : after_alls) a();

include/description.hpp

Lines changed: 87 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <string>
1010
#include <deque>
1111
#include <queue>
12+
#include <forward_list>
1213
#include "it.hpp"
1314
#include "class_description.hpp"
1415

@@ -18,18 +19,28 @@ template <typename T>
1819
class ClassDescription; // forward-declaration for ClassDescription
1920

2021
class Description : public Runnable {
22+
using VoidBlock = std::function<void()>;
23+
2124
public:
2225
using Block = std::function<void(Description &)>;
23-
using VoidBlock = std::function<void()>;
26+
27+
const bool has_subject = false;
28+
std::forward_list<LetBase *> lets;
29+
std::deque<VoidBlock> after_alls;
30+
std::deque<VoidBlock> before_eaches;
31+
std::deque<VoidBlock> after_eaches;
2432

2533
private:
2634
Block block;
2735

2836
protected:
2937
std::string description = "";
3038

31-
Description() {}
32-
39+
// These two constructors are the most basic ones,
40+
// used to create Descriptions with only their description
41+
// field initialized. They should only be used by subclasses
42+
// of Description.
43+
Description() = default;
3344
explicit Description(std::string description) noexcept
3445
: description(description) {}
3546

@@ -42,22 +53,21 @@ class Description : public Runnable {
4253
void exec_after_eaches();
4354

4455
public:
45-
// Constructor
56+
// Copy constructor
57+
Description(const Description &copy) = default;
58+
59+
// Primary constructor. Entry of all specs.
4660
Description(std::string description, Block block) noexcept
4761
: block(block),
4862
description(description) {}
4963

50-
const bool has_subject = false;
51-
std::unordered_set<LetBase *> lets;
52-
std::deque<VoidBlock> after_alls;
53-
std::deque<VoidBlock> before_eaches;
54-
std::deque<VoidBlock> after_eaches;
64+
/********* Specify/It *********/
5565

56-
// Specify/It functions
5766
Result it(std::string description, ItD::Block body);
5867
Result it(ItD::Block body);
5968

60-
// Context functions
69+
/********* Context ***********/
70+
6171
Result context(std::string name, Block body);
6272

6373
template <class T>
@@ -71,34 +81,34 @@ class Description : public Runnable {
7181
Result context(std::initializer_list<U> init_list,
7282
std::function<void(ClassDescription<T> &)> block);
7383

84+
/********* Each/All *********/
85+
7486
void before_each(VoidBlock block);
7587
void before_all(VoidBlock block);
7688
void after_each(VoidBlock block);
7789
void after_all(VoidBlock block);
7890

91+
/********* Let *********/
92+
7993
template <typename T>
8094
auto let(T body) -> Let<decltype(body())>;
8195
void reset_lets() noexcept;
8296

83-
Result run(Formatters::BaseFormatter &printer) override;
97+
/********* Standard getters *********/
8498

85-
virtual std::string get_description() noexcept { return description; }
86-
virtual const std::string get_description() const noexcept {
87-
return description;
88-
}
99+
virtual std::string get_description() const noexcept { return description; }
100+
virtual std::string get_subject_type() const noexcept { return ""; }
101+
102+
/********* Run *********/
89103

90-
virtual std::string get_subject_type() noexcept { return ""; }
91-
virtual const std::string get_subject_type() const noexcept { return ""; }
104+
Result run(Formatters::BaseFormatter &printer) override;
92105
};
93106

94107
using Context = Description;
95108

96-
inline Result Description::context(std::string description, Block body) {
97-
Context context(*this, description, body);
98-
context.before_eaches = this->before_eaches;
99-
context.after_eaches = this->after_eaches;
100-
return context.run(this->get_formatter());
101-
}
109+
/*>>>>>>>>>>>>>>>>>>>> Description <<<<<<<<<<<<<<<<<<<<<<<<<*/
110+
111+
/*========= Description::it =========*/
102112

103113
inline Result Description::it(std::string description, ItD::Block block) {
104114
ItD it(*this, description, block);
@@ -116,6 +126,17 @@ inline Result Description::it(ItD::Block block) {
116126
return result;
117127
}
118128

129+
/*========= Description::context =========*/
130+
131+
inline Result Description::context(std::string description, Block body) {
132+
Context context(*this, description, body);
133+
context.before_eaches = this->before_eaches;
134+
context.after_eaches = this->after_eaches;
135+
return context.run(this->get_formatter());
136+
}
137+
138+
/*========= Description:: each/alls =========*/
139+
119140
inline void Description::before_each(VoidBlock b) {
120141
before_eaches.push_back(b);
121142

@@ -134,14 +155,18 @@ inline void Description::after_each(VoidBlock b) { after_eaches.push_back(b); }
134155

135156
inline void Description::after_all(VoidBlock b) { after_alls.push_back(b); }
136157

158+
/*----------- private -------------*/
159+
137160
inline void Description::exec_before_eaches() {
138-
for (VoidBlock b : before_eaches) b();
161+
for (VoidBlock &b : before_eaches) b();
139162
}
140163

141164
inline void Description::exec_after_eaches() {
142-
for (VoidBlock b : after_eaches) b();
165+
for (VoidBlock &b : after_eaches) b();
143166
}
144167

168+
/*========= Description::let =========*/
169+
145170
/**
146171
* @brief Object generator for Let.
147172
*
@@ -150,26 +175,48 @@ inline void Description::exec_after_eaches() {
150175
* @return a new Let object
151176
*/
152177
template <typename T>
153-
inline auto Description::let(T block) -> Let<decltype(block())> {
154-
Let<decltype(block())> let(block);
155-
lets.insert(&let);
156-
return let;
157-
}
158-
159-
inline Result Description::run(Formatters::BaseFormatter &printer) {
160-
if (not this->has_formatter()) this->set_printer(printer);
161-
printer.format(*this);
162-
block(*this);
163-
for (auto a : after_alls) a();
164-
if (this->get_parent() == nullptr) printer.flush();
165-
return this->get_status() ? Result::success() : Result::failure();
178+
auto Description::let(T block) -> Let<decltype(block())> {
179+
// In reality, this gets inlined due to the fact that it's
180+
// a templated function. Otherwise we wouldn't be able to
181+
// add the address of the Let, return the Let by value,
182+
// and still be able to do a valid deference of the Let
183+
// pointer later on when we needed to reset the Let.
184+
185+
Let<decltype(block())> let(block); // Create a Let
186+
lets.push_front(&let); // Add it to our list
187+
return let; // Hand it object off
166188
}
167189

190+
// TODO: Should this be protected?
168191
inline void Description::reset_lets() noexcept {
192+
// For every let in our list, reset it.
169193
for (auto &let : lets) let->reset();
170-
if (this->has_parent()) this->get_parent_as<Description *>()->reset_lets();
194+
195+
// Recursively reset all the lets in the family tree
196+
if (this->has_parent()) {
197+
this->get_parent_as<Description *>()->reset_lets();
198+
}
171199
}
172200

201+
/*========= Description::run =========*/
202+
203+
inline Result Description::run(Formatters::BaseFormatter &formatter) {
204+
// If there isn't already a formatter in the family tree, set ours.
205+
if (!this->has_formatter()) this->set_formatter(formatter);
206+
207+
formatter.format(*this); // Format our description in some way
208+
block(*this); // Run the block
209+
for (VoidBlock &a : after_alls) a(); // Run all our after_alls
210+
if (!this->has_parent()) formatter.flush(); // Inform the printer we're done
211+
212+
// Return success or failure
213+
return this->get_status() ? Result::success() : Result::failure();
214+
}
215+
216+
/*>>>>>>>>>>>>>>>>>>>> ItD <<<<<<<<<<<<<<<<<<<<<<<<<*/
217+
218+
/*========= ItD::run =========*/
219+
173220
inline Result ItD::run(Formatters::BaseFormatter &printer) {
174221
block(*this);
175222
printer.format(*this);

include/expectations/expectation.hpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,7 @@ class Expectation : public Child {
5151
bool ignore_failure = false;
5252

5353
public:
54-
Expectation(Expectation const &copy)
55-
: Child(copy.get_parent()),
56-
// block(copy.block),
57-
// has_block(copy.has_block),
58-
is_positive(copy.is_positive),
59-
ignore_failure(copy.ignore_failure) {}
54+
Expectation(const Expectation &) = default;
6055

6156
/**
6257
* @brief Create an Expectation using a value.
@@ -65,7 +60,7 @@ class Expectation : public Child {
6560
*
6661
* @return The constructed Expectation.
6762
*/
68-
Expectation(ItBase &it) : Child(it) {}
63+
explicit Expectation(ItBase &it) : Child(Child::of(it)) {}
6964

7065
/** @brief Get the target of the expectation. */
7166
// virtual const A &get_target() const & { return target; }
@@ -520,7 +515,7 @@ class ExpectationFunc : public Expectation<decltype(std::declval<F>()())> {
520515
// Expectation<A>::get_target()(); }
521516

522517
ExpectationFunc &not_() override {
523-
this->is_positive = not this->is_positive;
518+
this->is_positive = !this->is_positive;
524519
return *this;
525520
}
526521

0 commit comments

Comments
 (0)