Skip to content

Commit 434d0c2

Browse files
committed
Finished lets
1 parent a1dc140 commit 434d0c2

File tree

8 files changed

+175
-94
lines changed

8 files changed

+175
-94
lines changed

examples/sample/example_spec.cpp

Lines changed: 47 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@
55

66

77
describe bool_spec("Some Tests", $ {
8-
// context("true is", _ {
9-
// it("true", _ {
10-
// expect(true).to_be;
11-
// });
12-
// });
8+
context("true is", _ {
9+
it("true", _ {
10+
expect(static_cast<bool>(1)).to_equal(true);
11+
});
12+
13+
it("true", _ {
14+
expect(true).to_equal(true);
15+
});
16+
17+
});
1318

1419
int i = 4;
1520
explain("4", _ {
@@ -75,6 +80,7 @@ describe bool_spec("Some Tests", $ {
7580
});
7681
});
7782

83+
7884
// context("std::map {{1,2},{3,4},{5,6}}", _ {
7985
// it("includes 1", _ {
8086
// std::map<int,int> m = {{1,2},{3,4},{5,6}};
@@ -93,22 +99,6 @@ describe bool_spec("Some Tests", $ {
9399
// expect({1,2,3}).not_().to_include({4,5,6});
94100
// });
95101
// });
96-
97-
// before("each", _ {
98-
// n = rand();
99-
// });
100-
101-
// context("argument is positive", _ {
102-
// it("return positive", _ {
103-
// expect_to_equal(fabs(n), n);
104-
// });
105-
// });
106-
107-
// context("argument is negative", _ {
108-
// it("return positive", _ {
109-
// expect(fabs(-n).to(equal(n));
110-
// });
111-
// });
112102
});
113103

114104
describe abs_spec("abs", $ {
@@ -141,40 +131,48 @@ describe abs_spec("abs", $ {
141131
});
142132

143133

134+
/* Here is the description of strcmp */
135+
describe strcmp_spec("int strcmp ( const char * str1, const char * str2 )", $ {
136+
auto greater_than_zero = [](int i){return i>=0;};
137+
auto less_than_zero = [](int i){return i<0;};
144138

139+
it("returns 0 only when strings are equal", _ {
140+
expect(strcmp("hello", "hello")).to_equal(0);
141+
});
145142

143+
it("returns a negative integer when str1 is less than str2", _ {
144+
expect(strcmp("hello", "world")).to_be(less_than_zero);
145+
expect(strcmp("0123", "1321431")).to_be(less_than_zero);
146+
});
146147

148+
it("returns a positive integer if str1 is greater than str2", _ {
149+
expect(strcmp("yellow", "world")).to_be(greater_than_zero);
150+
expect(strcmp("9", "789")).to_be(greater_than_zero);
151+
});
152+
});
147153

154+
describe_a <std::vector<int>> vector_spec({1,2,3,4}, $ {
155+
it("should contain 2", _ {
156+
expect({1,2,3,4}).to_include(2);
157+
});
148158

159+
it( _ { is_expected().to_include(2); });
160+
});
149161

162+
int _count = 0;
163+
describe let_spec("let", $ {
164+
let(count, [&]{ return ++_count ;});
165+
166+
it("memoizes the value", _ {
167+
expect(count).to_equal(1);
168+
expect(count).to_equal(1);
169+
});
150170

151-
152-
153-
154-
155-
/* Here is the description of strcmp */
156-
// describe strcmp_spec("int strcmp ( const char * str1, const char * str2 )", _ {
157-
// it( "returns 0 only when strings are equal", _ {
158-
// // should_equal( strcmp("hello", "hello"), 0);
159-
// // should_not_be_null( strcmp("hello", "world") );
160-
// });
161-
162-
// it( "returns a negative integer when str1 is less than str2", _ {
163-
// // should_be_true( strcmp("hello", "world") < 0 );
164-
// // should_be_true( strcmp("0123", "1321431") < 0 );
165-
// });
166-
167-
// it( "returns a positive integer if str1 is greater than str2", _ {
168-
// // should_be_true( strcmp("yellow", "world") > 0 );
169-
// // should_be_true( strcmp("9", "789") > 0 );
170-
// });
171-
// });
172-
173-
describe_a <std::vector<int>> vector_spec({1,2,3,4}, $ {
174-
it("should contain 2", _ {
175-
expect({1,2,3,4}).to_include(6);
176-
});
171+
it("is not cached across examples", _ {
172+
expect(count).to_equal(2);
177173
});
174+
});
175+
178176

179177
// describe_a<std::vector<int>> another_vector_spec({1,2,3,4}, _ {
180178
// // it(_ { assert(static_cast<ClassDescription<std::vector<int>>*>(self.get_parent()) != nullptr); });
@@ -185,11 +183,6 @@ describe_a <std::vector<int>> vector_spec({1,2,3,4}, $ {
185183
// });
186184
// });
187185

188-
describe_a <std::vector<int>> another_vector_spec({1,2,3,4}, $ {
189-
it( _ { is_expected().to_include(6); });
190-
});
191-
192-
193186
describe list_spec("A list spec", $ {
194187
explain <std::list<int>> ({1,2,3,4}, _ {
195188
it( _ { is_expected().to_include(6); });
@@ -201,8 +194,9 @@ int main(){
201194
bool r = true;
202195
r &= bool_spec.run();
203196
r &= abs_spec.run();
197+
r &= strcmp_spec.run();
204198
r &= vector_spec.run();
205-
r &= another_vector_spec.run();
199+
r &= let_spec.run();
206200
// #undef expect
207201
// #undef it
208202
// Description d("halp", _ {});

include/class_description.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,23 @@ bool ClassDescription<T>::run() {
220220
return this->get_status();
221221
}
222222

223+
template <class T>
224+
Expectations::Expectation<T> ItCd<T>::is_expected() {
225+
auto cd = static_cast<ClassDescription<T>*>(this->get_parent());
226+
Expectations::Expectation<T> expectation(cd->get_subject());
227+
expectation.set_parent(this);
228+
return expectation;
229+
}
230+
231+
template <class T>
232+
bool ItCd<T>::run() {
233+
if (!this->needs_descr()) {
234+
std::cout << padding() << get_descr() << std::endl;
235+
}
236+
body(*this);
237+
auto cd = static_cast<ClassDescription<T>*>(this->get_parent());
238+
cd->reset_lets();
239+
return this->get_status();
240+
}
241+
223242
#endif /* CLASS_DESCRIPTION_H */

include/cppspec.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#define after_each self.after_each
1717
#define let(name, body) \
1818
auto name = make_let(#name, body); \
19-
self.let(#name, name)
19+
self.let(#name, name);
2020

2121
typedef Description describe;
2222

include/description.hpp

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ class Description : public Runnable {
6666
void exec_before_eaches();
6767
void exec_after_eaches();
6868

69-
void let(std::string name, Runnable &body);
70-
69+
void let(std::string, Runnable &body);
7170
bool run();
71+
void reset_lets();
72+
Runnable *find_let(std::string);
7273
};
7374

7475
typedef Description Context;
@@ -128,7 +129,8 @@ void Description::before_each(rule_block_t b) {
128129
// Due to how lambdas and their contexts are passed around, we need to prime
129130
// the environment by executing the before_each, so that when an 'it'
130131
// declaration's lambda captures that env, it has the correct values for the
131-
// variables. Truthfully, 'before_each' is a misnomer, as they are not getting
132+
// variables. Truthfully, 'before_each' is a misnomer, as they are not
133+
// getting
132134
// executed directly before the lambda's execution as one might expect, but
133135
// instead before the *next* lambda is declared.
134136
b();
@@ -149,8 +151,7 @@ void Description::exec_after_eaches() {
149151
}
150152

151153
void Description::let(std::string name, Runnable &body) {
152-
auto p = lets.insert({name, &body});
153-
if (!p.second) p.first->second = &body; // assign if the key is already there
154+
lets.insert({name, &body});
154155
}
155156

156157
bool Description::run() {
@@ -161,4 +162,53 @@ bool Description::run() {
161162
return this->get_status();
162163
}
163164

165+
void Description::reset_lets() {
166+
for (auto &pair : lets) {
167+
auto base = static_cast<LetBase *>(pair.second); // downcast.
168+
base->reset();
169+
}
170+
171+
if (has_parent()) {
172+
auto parent = static_cast<Description *>(get_parent());
173+
parent->reset_lets();
174+
}
175+
}
176+
177+
Runnable *Description::find_let(std::string name) {
178+
auto got = lets.find(name);
179+
180+
if (got == lets.end()) {
181+
if (this->has_parent()) {
182+
auto parent = static_cast<Description *>(get_parent());
183+
return parent->find_let(name);
184+
} else { // this should never, *ever* happen.
185+
throw(std::out_of_range("Could not find let '" + name + "'"));
186+
}
187+
} else {
188+
return got->second;
189+
}
190+
}
191+
192+
template <class T>
193+
Expectations::Expectation<T> ItExpBase::expect(Let<T> let) {
194+
auto parent = static_cast<Description *>(this->get_parent());
195+
Let<T> *actual_let = static_cast<Let<T> *>(parent->find_let(let.get_name()));
196+
T res = actual_let->get_result();
197+
Expectations::Expectation<T> expectation(res);
198+
expectation.set_parent(this);
199+
return expectation;
200+
}
201+
202+
bool ItD::run() {
203+
if (!this->needs_descr()) {
204+
std::cout << padding() << get_descr() << std::endl;
205+
}
206+
body(*this);
207+
208+
auto parent = static_cast<Description *>(this->get_parent());
209+
parent->reset_lets();
210+
211+
return this->get_status();
212+
}
213+
164214
#endif /* DESCRIPTION_H */

include/expectations/expectation.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <functional>
44
#include <vector>
55
#include "runnable.hpp"
6+
#include "let.hpp"
67
#include "matchers/basematcher.hpp"
78
#include "matchers/be.hpp"
89
#include "matchers/be_between.hpp"
@@ -59,6 +60,8 @@ class Expectation : public Child {
5960
*
6061
* @return The constructed Expectation.
6162
*/
63+
// TODO: create a "lazy" parameter for differentiating between delayed and
64+
// immediate execution
6265
Expectation(std::function<A(void)> block) : block(block), has_block(true) {}
6366

6467
/**

include/it.hpp

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,26 @@
22
#define IT_H
33
#include <string>
44
#include <functional>
5+
#include <unordered_map>
6+
#include "it_base.hpp"
57
#include "expectations/expectation.hpp"
68

7-
class Description;
8-
9-
template <class T>
10-
class ClassDescription;
11-
129
class ItExpBase : public ItBase {
1310
public:
1411
ItExpBase() : ItBase(){};
1512
ItExpBase(std::string descr) : ItBase(descr){};
1613
template <class U>
1714
Expectations::Expectation<U> expect(U value);
1815

16+
// template <class U>
17+
// Expectations::Expectation<U> expect(U &value);
18+
1919
template <class U>
2020
Expectations::Expectation<std::vector<U>> expect(
2121
std::initializer_list<U> init_list);
22+
23+
template <class U>
24+
Expectations::Expectation<U> expect(Let<U> let);
2225
};
2326

2427
class ItD : public ItExpBase {
@@ -65,6 +68,13 @@ Expectations::Expectation<T> ItExpBase::expect(T value) {
6568
return expectation;
6669
}
6770

71+
// template <class T>
72+
// Expectations::Expectation<T> ItExpBase::expect(T const &value) {
73+
// Expectations::Expectation<T> expectation(value);
74+
// expectation.set_parent(this);
75+
// return expectation;
76+
// }
77+
6878
/**
6979
* @brief An expect for initializer_list subjects
7080
*
@@ -80,29 +90,4 @@ Expectations::Expectation<std::vector<T>> ItExpBase::expect(
8090
return expectation;
8191
}
8292

83-
template <class T>
84-
Expectations::Expectation<T> ItCd<T>::is_expected() {
85-
auto cd = static_cast<ClassDescription<T> *>(this->get_parent());
86-
Expectations::Expectation<T> expectation(cd->get_subject());
87-
expectation.set_parent(this);
88-
return expectation;
89-
}
90-
91-
bool ItD::run() {
92-
if (!this->needs_descr()) {
93-
std::cout << padding() << get_descr() << std::endl;
94-
}
95-
body(*this);
96-
return this->get_status();
97-
}
98-
99-
template <class T>
100-
bool ItCd<T>::run() {
101-
if (!this->needs_descr()) {
102-
std::cout << padding() << get_descr() << std::endl;
103-
}
104-
body(*this);
105-
return this->get_status();
106-
}
107-
10893
#endif /* IT_H */

0 commit comments

Comments
 (0)