Skip to content

Commit ea9f909

Browse files
committed
Bug fixes
1 parent 3464886 commit ea9f909

5 files changed

Lines changed: 32 additions & 35 deletions

File tree

include/cppspec.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#define before_each self.before_each
3232
#define after_all self.after_all
3333
#define after_each self.after_each
34-
#define let(name, body) auto(name) = self.let(body);
34+
#define let(name, body) auto(name) = self.let(body); self.register_let(&(name));
3535

3636
#ifdef CPPSPEC_SEMIHOSTED
3737
#define CPPSPEC_MAIN(spec) \

include/description.hpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class Description : public Runnable {
9898

9999
template <typename T>
100100
auto let(T body) -> Let<decltype(body())>;
101+
void register_let(LetBase* let) noexcept;
101102
void reset_lets() noexcept;
102103

103104
/********* Standard getters *********/
@@ -197,15 +198,13 @@ inline void Description::exec_after_eaches() {
197198
*/
198199
template <typename T>
199200
auto Description::let(T block) -> Let<decltype(block())> {
200-
// In reality, this gets inlined due to the fact that it's
201-
// a templated function. Otherwise we wouldn't be able to
202-
// add the address of the Let, return the Let by value,
203-
// and still be able to do a valid deference of the Let
204-
// pointer later on when we needed to reset the Let.
205-
206-
Let<decltype(block())> let(block); // Create a Let
207-
lets.push_front(&let); // Add it to our list
208-
return let; // Hand it object off
201+
return Let<decltype(block())>(block);
202+
}
203+
204+
// Register a let variable for reset between examples.
205+
// Must be called with the address of the variable that holds the returned Let.
206+
inline void Description::register_let(LetBase* let) noexcept {
207+
lets.push_front(let);
209208
}
210209

211210
// TODO: Should this be protected?

include/expectations/expectation.hpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <exception>
4+
#include <optional>
45
#include <regex>
56
#include <source_location>
67
#include <string>
@@ -116,7 +117,9 @@ class Expectation {
116117
void to_match(std::string str, std::string msg = "");
117118
void to_partially_match(std::regex regex, std::string msg = "");
118119
void to_partially_match(std::string str, std::string msg = "");
119-
void to_satisfy(std::function<bool(A)> /*test*/, std::string msg = "");
120+
template <typename F>
121+
requires std::invocable<F, A> && std::convertible_to<std::invoke_result_t<F, A>, bool>
122+
void to_satisfy(F test, std::string msg = "");
120123
void to_start_with(std::string start, std::string msg = "");
121124

122125
template <typename U>
@@ -355,8 +358,10 @@ void Expectation<A>::to_partially_match(std::regex regex, std::string msg) {
355358
* @return Whether the expectation succeeds or fails.
356359
*/
357360
template <typename A>
358-
void Expectation<A>::to_satisfy(std::function<bool(A)> test, std::string msg) {
359-
Matchers::Satisfy<A>(*this, test).set_message(std::move(msg)).run();
361+
template <typename F>
362+
requires std::invocable<F, A> && std::convertible_to<std::invoke_result_t<F, A>, bool>
363+
void Expectation<A>::to_satisfy(F test, std::string msg) {
364+
Matchers::Satisfy<A>(*this, std::function<bool(A)>(std::move(test))).set_message(std::move(msg)).run();
360365
}
361366

362367
template <typename A>
@@ -377,8 +382,8 @@ void Expectation<A>::to_end_with(std::string ending, std::string msg) {
377382

378383
template <typename A>
379384
template <typename U>
380-
void Expectation<A>::to_end_with(std::initializer_list<U> start_sequence, std::string msg) {
381-
Matchers::StartWith<A, std::initializer_list<U>>(*this, start_sequence).set_message(std::move(msg)).run();
385+
void Expectation<A>::to_end_with(std::initializer_list<U> end_sequence, std::string msg) {
386+
Matchers::EndWith<A, std::initializer_list<U>>(*this, end_sequence).set_message(std::move(msg)).run();
382387
}
383388

384389
template <typename A>
@@ -438,7 +443,7 @@ template <Util::is_functional F>
438443
class ExpectationFunc : public Expectation<decltype(std::declval<F>()())> {
439444
using block_ret_t = decltype(std::declval<F>()());
440445
F block;
441-
std::shared_ptr<block_ret_t> computed = nullptr;
446+
std::optional<block_ret_t> computed = std::nullopt;
442447

443448
public:
444449
ExpectationFunc(ExpectationFunc<F> const& copy, std::source_location location)
@@ -473,8 +478,8 @@ class ExpectationFunc : public Expectation<decltype(std::declval<F>()())> {
473478

474479
/** @brief Get the target of the expectation. */
475480
block_ret_t& get_target() & override {
476-
if (computed == nullptr) {
477-
computed = std::make_shared<block_ret_t>(block());
481+
if (!computed.has_value()) {
482+
computed.emplace(block());
478483
}
479484
return *computed;
480485
}

include/result.hpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @file */
22
#pragma once
33

4-
#include <ciso646>
4+
#include <version>
55
#include <format>
66
#include <source_location>
77
#include <sstream>
@@ -25,17 +25,13 @@ class Result {
2525
[[nodiscard]] bool is_error() const noexcept { return status_ == Status::Error; }
2626

2727
static Result reduce(const Result& lhs, const Result& rhs) noexcept {
28-
if (lhs.is_failure()) {
29-
return lhs;
30-
} else if (rhs.is_failure()) {
31-
return rhs;
32-
} else if (lhs.is_success()) {
33-
return lhs;
34-
} else if (rhs.is_success()) {
35-
return rhs;
36-
} else {
37-
return lhs;
38-
}
28+
if (lhs.is_failure()) return lhs;
29+
if (rhs.is_failure()) return rhs;
30+
if (lhs.is_error()) return lhs;
31+
if (rhs.is_error()) return rhs;
32+
if (lhs.is_success()) return lhs;
33+
if (rhs.is_success()) return rhs;
34+
return lhs;
3935
}
4036

4137
/*--------- Location helper functions ------------*/
@@ -45,11 +41,9 @@ class Result {
4541
}
4642

4743
[[nodiscard]] std::string get_type() const noexcept { return type; }
48-
[[nodiscard]] std::string get_type() noexcept { return type; }
4944
void set_type(std::string type) noexcept { this->type = std::move(type); }
5045

5146
/*--------- Message helper functions -------------*/
52-
std::string get_message() noexcept { return message; }
5347
[[nodiscard]] std::string get_message() const noexcept { return message; }
5448
Result& set_message(std::string message) noexcept {
5549
this->message = std::move(message);

include/runnable.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,9 @@ class Runnable {
9999
virtual void timed_run() {
100100
using namespace std::chrono;
101101
start_time_ = system_clock::now();
102-
time_point start_time = high_resolution_clock::now();
102+
auto start = steady_clock::now();
103103
run();
104-
time_point end = high_resolution_clock::now();
105-
runtime_ = end - start_time;
104+
runtime_ = steady_clock::now() - start;
106105
}
107106

108107
[[nodiscard]] std::chrono::duration<double> get_runtime() const { return runtime_; }

0 commit comments

Comments
 (0)