Skip to content

Commit cf05829

Browse files
authored
Merge pull request #125 from steve-downey/more_coverage
More coverage
2 parents 68e7a97 + 3b592b6 commit cf05829

File tree

7 files changed

+211
-10
lines changed

7 files changed

+211
-10
lines changed

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,15 @@ lint-manual: ## Run all manual tools in pre-commit
167167

168168
.PHONY: coverage
169169
coverage: ## Build and run the tests with the GCOV profile and process the results
170-
coverage: venv
170+
coverage: venv $(_build_path)/CMakeCache.txt
171171
$(ACTIVATE) cmake --build $(_build_path) --config Gcov
172172
$(ACTIVATE) ctest --build-config Gcov --output-on-failure --test-dir $(_build_path)
173173
$(ACTIVATE) cmake --build $(_build_path) --config Gcov --target process_coverage
174174

175+
.PHONY: view-coverage
176+
view-coverage: ## View the coverage report
177+
sensible-browser $(_build_path)/coverage/coverage.html
178+
175179
# Help target
176180
.PHONY: help
177181
help: ## Show this help.

etc/clang-20-toolchain.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ include_guard(GLOBAL)
77

88
set(CMAKE_C_COMPILER clang-20)
99
set(CMAKE_CXX_COMPILER clang++-20)
10+
set(GCOV_EXECUTABLE "llvm-cov-20 gcov" CACHE STRING "GCOV executable" FORCE)
1011

1112
include("${CMAKE_CURRENT_LIST_DIR}/clang-flags.cmake")

etc/clang-21-toolchain.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ include_guard(GLOBAL)
77

88
set(CMAKE_C_COMPILER clang-21)
99
set(CMAKE_CXX_COMPILER clang++-21)
10+
set(GCOV_EXECUTABLE "llvm-cov-21 gcov" CACHE STRING "GCOV executable" FORCE)
1011

1112
include("${CMAKE_CURRENT_LIST_DIR}/clang-flags.cmake")

etc/gcc-flags.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ set(CMAKE_CXX_FLAGS_ASAN
3636
)
3737

3838
set(CMAKE_CXX_FLAGS_GCOV
39-
"-O0 -fno-inline -g --coverage -fprofile-abs-path"
39+
"-O0 -fno-default-inline -fno-inline -g --coverage -fprofile-abs-path"
4040
CACHE STRING
4141
"C++ GCOV Flags"
4242
FORCE

tests/beman/optional/optional.t.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,53 @@ TEST(OptionalTest, OptionalOfOptional) {
153153
EXPECT_TRUE(oo2.value() == 43);
154154
}
155155

156+
TEST(OptionalTest, EmplaceVariadic) {
157+
struct for_emplace {
158+
int a;
159+
int b;
160+
int c;
161+
} f{4, 5, 6};
162+
163+
beman::optional::optional<for_emplace> o3;
164+
o3.emplace(1, 2, 3);
165+
EXPECT_TRUE(o3.has_value());
166+
167+
beman::optional::optional<for_emplace> engaged{f};
168+
engaged.emplace(1, 2, 3);
169+
EXPECT_TRUE(engaged.has_value());
170+
EXPECT_EQ(engaged->a, 1);
171+
}
172+
173+
TEST(OptionalTest, EmplaceInitializerList) {
174+
struct for_emplace {
175+
std::vector<int> v; // something to construct with list
176+
std::string name = "";
177+
for_emplace(std::initializer_list<int> l) : v(l) {}
178+
for_emplace(std::initializer_list<int> l, std::string n) : v(l), name(n) {}
179+
} f{{1, 2, 3}};
180+
181+
beman::optional::optional<for_emplace> o3;
182+
o3.emplace({1, 2, 3});
183+
EXPECT_TRUE(o3.has_value());
184+
185+
beman::optional::optional<for_emplace> engaged{f};
186+
187+
auto e1 = engaged.emplace({1, 2, 3});
188+
189+
EXPECT_TRUE(engaged.has_value());
190+
EXPECT_EQ(engaged->v[0], 1);
191+
EXPECT_EQ(engaged->name, std::string(""));
192+
EXPECT_EQ(engaged->v[0], e1.v[0]);
193+
EXPECT_EQ(engaged->name, e1.name);
194+
195+
auto e2 = engaged.emplace({2, 3, 4}, "Name");
196+
EXPECT_TRUE(engaged.has_value());
197+
EXPECT_EQ(engaged->v[0], 2);
198+
EXPECT_EQ(engaged->name, std::string("Name"));
199+
EXPECT_EQ(engaged->v[0], e2.v[0]);
200+
EXPECT_EQ(engaged->name, e2.name);
201+
}
202+
156203
TEST(OptionalTest, AssignmentValue) {
157204
beman::optional::optional<int> o1 = 42;
158205
beman::optional::optional<int> o2 = 12;
@@ -192,6 +239,15 @@ TEST(OptionalTest, AssignmentValue) {
192239
o1 = s;
193240
EXPECT_TRUE(*o1 == 54);
194241

242+
beman::optional::optional<short> emptyShort;
243+
o1 = emptyShort;
244+
EXPECT_FALSE(o1);
245+
246+
o1 = o4;
247+
EXPECT_TRUE(*o1 == 42);
248+
o1 = std::move(emptyShort);
249+
EXPECT_FALSE(o1);
250+
195251
struct not_trivial_copy_assignable {
196252
int i_;
197253
constexpr not_trivial_copy_assignable(int i) : i_(i) {}
@@ -243,6 +299,58 @@ TEST(OptionalTest, AssignmentValue) {
243299
EXPECT_FALSE(o8);
244300
}
245301

302+
TEST(OptionalTest, ConvertingAssignmentValue) {
303+
beman::optional::optional<int> o1 = 42;
304+
beman::optional::optional<int> o2;
305+
306+
short s = 9;
307+
o1 = s;
308+
o2 = s;
309+
EXPECT_TRUE(o1);
310+
EXPECT_TRUE(o2);
311+
}
312+
313+
TEST(OptionalTest, ConvertingValueAssignment) {
314+
struct base {};
315+
316+
struct convertible {
317+
operator base() { return base{}; }
318+
};
319+
320+
beman::optional::optional<base> empty;
321+
beman::optional::optional<base> engaged(base{});
322+
323+
empty = convertible{};
324+
engaged = convertible{};
325+
EXPECT_TRUE(empty);
326+
EXPECT_TRUE(engaged);
327+
}
328+
329+
TEST(OptionalTest, ValueObserver) {
330+
beman::optional::optional<int> empty;
331+
beman::optional::optional<int> bound{5};
332+
EXPECT_TRUE(bound);
333+
EXPECT_FALSE(empty);
334+
EXPECT_EQ(*bound, 5);
335+
EXPECT_EQ(bound.value(), 5);
336+
EXPECT_EQ(std::as_const(bound).value(), 5);
337+
EXPECT_EQ(std::move(bound).value(), 5);
338+
339+
EXPECT_THROW(
340+
{
341+
try {
342+
empty.value();
343+
} catch (const beman::optional::bad_optional_access& e) {
344+
EXPECT_STREQ("Optional has no value", e.what());
345+
throw;
346+
}
347+
},
348+
beman::optional::bad_optional_access);
349+
350+
EXPECT_THROW({ std::as_const(empty).value(); }, beman::optional::bad_optional_access);
351+
EXPECT_THROW({ std::move(empty).value(); }, beman::optional::bad_optional_access);
352+
}
353+
246354
TEST(OptionalTest, Triviality) {
247355
EXPECT_TRUE(std::is_trivially_copy_constructible<beman::optional::optional<int>>::value);
248356
EXPECT_TRUE(std::is_trivially_copy_assignable<beman::optional::optional<int>>::value);
@@ -401,6 +509,16 @@ TEST(OptionalTest, MakeOptional) {
401509
EXPECT_TRUE(o5->v[1] == 1);
402510
EXPECT_TRUE(std::get<0>(o5->t) == 2);
403511
EXPECT_TRUE(std::get<1>(o5->t) == 3);
512+
513+
struct for_variadic {
514+
int a;
515+
int b;
516+
int c;
517+
};
518+
519+
auto o6 = beman::optional::make_optional<for_variadic>(0, 1, 3);
520+
EXPECT_TRUE(o6);
521+
EXPECT_EQ(o6->a, 0);
404522
}
405523

406524
TEST(OptionalTest, Nullopt) {

tests/beman/optional/optional_constexpr.t.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ consteval bool testConstexprAssignmentValue() {
161161
o1 = s;
162162
retval &= (*o1 == 54);
163163

164+
beman::optional::optional<short> emptyShort;
165+
o1 = emptyShort;
166+
retval &= !o1.has_value();
167+
168+
o1 = o4;
169+
o1 = std::move(emptyShort);
170+
retval &= !o1.has_value();
171+
164172
struct not_trivial_copy_assignable {
165173
int i_;
166174
constexpr not_trivial_copy_assignable(int i) : i_(i) {}

tests/beman/optional/optional_ref.t.cpp

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ beman::optional::optional<Thing&> process() {
9292
return t;
9393
}
9494

95+
beman::optional::optional<Thing&> processEmpty() { return beman::optional::nullopt; }
96+
9597
TEST(OptionalRefTest, BaseDerivedCastConstruction) {
9698
base b;
9799
derived& dref(b); // ok
@@ -145,13 +147,76 @@ TEST(OptionalRefTest, Assignment) {
145147
o = process(); // well-formed
146148
EXPECT_TRUE(o);
147149

150+
o = processEmpty(); // well-formed
151+
EXPECT_FALSE(o);
152+
148153
beman::optional::optional<const int&> o2;
149154
EXPECT_FALSE(o2);
150155
o2 = [&]() { return i1; }();
151156

152157
EXPECT_EQ(*o2, 7);
153158
}
154159

160+
TEST(OptionalRefTest, NullOptAssignment) {
161+
beman::optional::optional<int&> i1;
162+
EXPECT_FALSE(i1);
163+
int i = 5;
164+
i1 = i;
165+
166+
EXPECT_TRUE(i1);
167+
i1 = beman::optional::nullopt;
168+
EXPECT_FALSE(i1);
169+
i1 = i;
170+
EXPECT_TRUE(i1);
171+
}
172+
173+
TEST(OptionalRefTest, ConstRefAssignment) {
174+
int i = 7;
175+
beman::optional::optional<int&> i1{i};
176+
const beman::optional::optional<int&> i2 = i1;
177+
178+
beman::optional::optional<const int&> c1;
179+
c1 = i2;
180+
EXPECT_TRUE(c1);
181+
EXPECT_EQ(*c1, 7);
182+
183+
i = 5;
184+
EXPECT_EQ(*c1, 5);
185+
const beman::optional::optional<int&> empty(beman::optional::nullopt);
186+
c1 = empty;
187+
EXPECT_FALSE(c1);
188+
}
189+
190+
TEST(OptionalRefTest, ConvertingConstRvalRef) {
191+
int i = 7;
192+
beman::optional::optional<int&> i1{i};
193+
const beman::optional::optional<int&> i2 = i1;
194+
195+
beman::optional::optional<const int&> c1;
196+
c1 = std::move(i2);
197+
EXPECT_TRUE(c1);
198+
EXPECT_EQ(*c1, 7);
199+
200+
i = 5;
201+
EXPECT_EQ(*c1, 5);
202+
const beman::optional::optional<int&> empty(beman::optional::nullopt);
203+
c1 = std::move(empty);
204+
EXPECT_FALSE(c1);
205+
}
206+
207+
TEST(OptionalRefTest, NullOptConstruction) {
208+
beman::optional::optional<int&> i1(beman::optional::nullopt);
209+
EXPECT_FALSE(i1);
210+
int i = 5;
211+
i1 = i;
212+
213+
EXPECT_TRUE(i1);
214+
i1 = beman::optional::nullopt;
215+
EXPECT_FALSE(i1);
216+
i1 = i;
217+
EXPECT_TRUE(i1);
218+
}
219+
155220
TEST(OptionalRefTest, RelationalOps) {
156221
int i1 = 4;
157222
int i2 = 42;
@@ -527,17 +592,21 @@ TEST(OptionalRefTest, Observers) {
527592
beman::optional::optional<int_box&> ob1 = i1;
528593
beman::optional::optional<int_box&> ob2;
529594
const beman::optional::optional<int_box&> ob3 = i1;
530-
success = std::is_same<decltype(ob1->i_), int>::value;
531-
static_assert(std::is_same<decltype(ob1->i_), int>::value);
595+
596+
EXPECT_EQ(ob1->i_, 3);
597+
EXPECT_EQ(ob3->i_, 3);
598+
599+
success = std::is_same_v<decltype(ob1->i_), int>;
600+
static_assert(std::is_same_v<decltype(ob1->i_), int>);
532601
EXPECT_TRUE(success);
533-
success = std::is_same<decltype(ob2->i_), int>::value;
534-
static_assert(std::is_same<decltype(ob2->i_), int>::value);
602+
success = std::is_same_v<decltype(ob2->i_), int>;
603+
static_assert(std::is_same_v<decltype(ob2->i_), int>);
535604
EXPECT_TRUE(success);
536-
success = std::is_same<decltype(ob3->i_), int>::value;
537-
static_assert(std::is_same<decltype(ob3->i_), int>::value);
605+
success = std::is_same_v<decltype(ob3->i_), int>;
606+
static_assert(std::is_same_v<decltype(ob3->i_), int>);
538607
EXPECT_TRUE(success);
539-
success = std::is_same<decltype(std::move(ob1)->i_), int>::value;
540-
static_assert(std::is_same<decltype(std::move(ob1)->i_), int>::value);
608+
success = std::is_same_v<decltype(std::move(ob1)->i_), int>;
609+
static_assert(std::is_same_v<decltype(std::move(ob1)->i_), int>);
541610
EXPECT_TRUE(success);
542611
}
543612

0 commit comments

Comments
 (0)