Put local functions from tests into anonymous namespaces.
This fixes some duplicate-symbol linker errors under Linux/Clang. Both generator_test.cpp and recursive_generator_tests.cpp were defining a 'range' function.
This commit is contained in:
parent
3d97b79294
commit
62cff52fd1
5 changed files with 172 additions and 145 deletions
|
@ -97,35 +97,38 @@ TEST_CASE("enumerate sequence of multiple values")
|
|||
}());
|
||||
}
|
||||
|
||||
class set_to_true_on_destruction
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
|
||||
set_to_true_on_destruction(bool* value)
|
||||
: m_value(value)
|
||||
{}
|
||||
|
||||
set_to_true_on_destruction(set_to_true_on_destruction&& other)
|
||||
: m_value(other.m_value)
|
||||
class set_to_true_on_destruction
|
||||
{
|
||||
other.m_value = nullptr;
|
||||
}
|
||||
public:
|
||||
|
||||
~set_to_true_on_destruction()
|
||||
{
|
||||
if (m_value != nullptr)
|
||||
set_to_true_on_destruction(bool* value)
|
||||
: m_value(value)
|
||||
{}
|
||||
|
||||
set_to_true_on_destruction(set_to_true_on_destruction&& other)
|
||||
: m_value(other.m_value)
|
||||
{
|
||||
*m_value = true;
|
||||
other.m_value = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
set_to_true_on_destruction(const set_to_true_on_destruction&) = delete;
|
||||
set_to_true_on_destruction& operator=(const set_to_true_on_destruction&) = delete;
|
||||
~set_to_true_on_destruction()
|
||||
{
|
||||
if (m_value != nullptr)
|
||||
{
|
||||
*m_value = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
set_to_true_on_destruction(const set_to_true_on_destruction&) = delete;
|
||||
set_to_true_on_destruction& operator=(const set_to_true_on_destruction&) = delete;
|
||||
|
||||
bool* m_value;
|
||||
};
|
||||
private:
|
||||
|
||||
bool* m_value;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("destructors of values in scope are called when async_generator destructed early")
|
||||
{
|
||||
|
|
|
@ -23,48 +23,51 @@ TEST_SUITE_BEGIN("file");
|
|||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
class temp_dir_fixture : public io_service_fixture
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
|
||||
temp_dir_fixture()
|
||||
class temp_dir_fixture : public io_service_fixture
|
||||
{
|
||||
auto tempDir = fs::temp_directory_path();
|
||||
public:
|
||||
|
||||
std::random_device random;
|
||||
for (int attempt = 1;; ++attempt)
|
||||
temp_dir_fixture()
|
||||
{
|
||||
m_path = tempDir / std::to_string(random());
|
||||
try
|
||||
auto tempDir = fs::temp_directory_path();
|
||||
|
||||
std::random_device random;
|
||||
for (int attempt = 1;; ++attempt)
|
||||
{
|
||||
fs::create_directories(m_path);
|
||||
return;
|
||||
}
|
||||
catch (const fs::filesystem_error&)
|
||||
{
|
||||
if (attempt == 10)
|
||||
m_path = tempDir / std::to_string(random());
|
||||
try
|
||||
{
|
||||
throw;
|
||||
fs::create_directories(m_path);
|
||||
return;
|
||||
}
|
||||
catch (const fs::filesystem_error&)
|
||||
{
|
||||
if (attempt == 10)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~temp_dir_fixture()
|
||||
{
|
||||
fs::remove_all(m_path);
|
||||
}
|
||||
~temp_dir_fixture()
|
||||
{
|
||||
fs::remove_all(m_path);
|
||||
}
|
||||
|
||||
const std::experimental::filesystem::path& temp_dir()
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
const std::experimental::filesystem::path& temp_dir()
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
std::experimental::filesystem::path m_path;
|
||||
std::experimental::filesystem::path m_path;
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE_FIXTURE(temp_dir_fixture, "write a file")
|
||||
{
|
||||
|
|
|
@ -159,15 +159,18 @@ TEST_CASE("generator throwing after first element rethrows out of operator++")
|
|||
}
|
||||
}
|
||||
|
||||
template<typename FIRST, typename SECOND>
|
||||
auto concat(FIRST&& first, SECOND&& second)
|
||||
namespace
|
||||
{
|
||||
using value_type = std::remove_reference_t<decltype(*first.begin())>;
|
||||
return [](FIRST first, SECOND second) -> cppcoro::generator<value_type>
|
||||
template<typename FIRST, typename SECOND>
|
||||
auto concat(FIRST&& first, SECOND&& second)
|
||||
{
|
||||
for (auto&& x : first) co_yield x;
|
||||
for (auto&& y : second) co_yield y;
|
||||
}(std::forward<FIRST>(first), std::forward<SECOND>(second));
|
||||
using value_type = std::remove_reference_t<decltype(*first.begin())>;
|
||||
return [](FIRST first, SECOND second) -> cppcoro::generator<value_type>
|
||||
{
|
||||
for (auto&& x : first) co_yield x;
|
||||
for (auto&& y : second) co_yield y;
|
||||
}(std::forward<FIRST>(first), std::forward<SECOND>(second));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("safe capture of r-value reference args")
|
||||
|
@ -190,11 +193,14 @@ TEST_CASE("safe capture of r-value reference args")
|
|||
CHECK(s == "foobuzzbaz");
|
||||
}
|
||||
|
||||
cppcoro::generator<int> range(int start, int end)
|
||||
namespace
|
||||
{
|
||||
for (; start < end; ++start)
|
||||
cppcoro::generator<int> range(int start, int end)
|
||||
{
|
||||
co_yield start;
|
||||
for (; start < end; ++start)
|
||||
{
|
||||
co_yield start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -320,20 +320,23 @@ TEST_CASE("exceptions thrown from nested call can be caught by caller")
|
|||
CHECK(iter == gen.end());
|
||||
}
|
||||
|
||||
recursive_generator<std::uint32_t> iterate_range(std::uint32_t begin, std::uint32_t end)
|
||||
namespace
|
||||
{
|
||||
if ((end - begin) <= 10u)
|
||||
recursive_generator<std::uint32_t> iterate_range(std::uint32_t begin, std::uint32_t end)
|
||||
{
|
||||
for (std::uint32_t i = begin; i < end; ++i)
|
||||
if ((end - begin) <= 10u)
|
||||
{
|
||||
co_yield i;
|
||||
for (std::uint32_t i = begin; i < end; ++i)
|
||||
{
|
||||
co_yield i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::uint32_t mid = begin + (end - begin) / 2;
|
||||
co_yield iterate_range(begin, mid);
|
||||
co_yield iterate_range(mid, end);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::uint32_t mid = begin + (end - begin) / 2;
|
||||
co_yield iterate_range(begin, mid);
|
||||
co_yield iterate_range(mid, end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,20 +375,23 @@ TEST_CASE("usage in standard algorithms")
|
|||
}
|
||||
}
|
||||
|
||||
recursive_generator<int> range(int start, int end)
|
||||
namespace
|
||||
{
|
||||
while (start < end)
|
||||
recursive_generator<int> range(int start, int end)
|
||||
{
|
||||
co_yield start++;
|
||||
while (start < end)
|
||||
{
|
||||
co_yield start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recursive_generator<int> range_chunks(int start, int end, int runLength, int stride)
|
||||
{
|
||||
while (start < end)
|
||||
recursive_generator<int> range_chunks(int start, int end, int runLength, int stride)
|
||||
{
|
||||
co_yield range(start, std::min(end, start + runLength));
|
||||
start += stride;
|
||||
while (start < end)
|
||||
{
|
||||
co_yield range(start, std::min(end, start + runLength));
|
||||
start += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
|
||||
TEST_SUITE_BEGIN("when_all");
|
||||
|
||||
template<template<typename T> class TASK, typename T>
|
||||
TASK<T> when_event_set_return(cppcoro::async_manual_reset_event& event, T value)
|
||||
namespace
|
||||
{
|
||||
co_await event;
|
||||
co_return std::move(value);
|
||||
template<template<typename T> class TASK, typename T>
|
||||
TASK<T> when_event_set_return(cppcoro::async_manual_reset_event& event, T value)
|
||||
{
|
||||
co_await event;
|
||||
co_return std::move(value);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("when_all() with no args completes immediately")
|
||||
|
@ -222,40 +225,43 @@ TEST_CASE("when_all() with vector<shared_task<>>")
|
|||
}()));
|
||||
}
|
||||
|
||||
template<template<typename T> class TASK>
|
||||
void check_when_all_vector_of_task_value()
|
||||
namespace
|
||||
{
|
||||
cppcoro::async_manual_reset_event event1;
|
||||
cppcoro::async_manual_reset_event event2;
|
||||
|
||||
bool whenAllCompleted = false;
|
||||
|
||||
cppcoro::sync_wait(cppcoro::when_all_ready(
|
||||
[&]() -> cppcoro::task<>
|
||||
template<template<typename T> class TASK>
|
||||
void check_when_all_vector_of_task_value()
|
||||
{
|
||||
std::vector<TASK<int>> tasks;
|
||||
cppcoro::async_manual_reset_event event1;
|
||||
cppcoro::async_manual_reset_event event2;
|
||||
|
||||
tasks.emplace_back(when_event_set_return<TASK>(event1, 1));
|
||||
tasks.emplace_back(when_event_set_return<TASK>(event2, 2));
|
||||
bool whenAllCompleted = false;
|
||||
|
||||
auto whenAllTask = cppcoro::when_all(std::move(tasks));
|
||||
cppcoro::sync_wait(cppcoro::when_all_ready(
|
||||
[&]() -> cppcoro::task<>
|
||||
{
|
||||
std::vector<TASK<int>> tasks;
|
||||
|
||||
auto& values = co_await whenAllTask;
|
||||
REQUIRE(values.size() == 2);
|
||||
CHECK(values[0] == 1);
|
||||
CHECK(values[1] == 2);
|
||||
tasks.emplace_back(when_event_set_return<TASK>(event1, 1));
|
||||
tasks.emplace_back(when_event_set_return<TASK>(event2, 2));
|
||||
|
||||
whenAllCompleted = true;
|
||||
}(),
|
||||
[&]() -> cppcoro::task<>
|
||||
{
|
||||
CHECK(!whenAllCompleted);
|
||||
event2.set();
|
||||
CHECK(!whenAllCompleted);
|
||||
event1.set();
|
||||
CHECK(whenAllCompleted);
|
||||
co_return;
|
||||
}()));
|
||||
auto whenAllTask = cppcoro::when_all(std::move(tasks));
|
||||
|
||||
auto& values = co_await whenAllTask;
|
||||
REQUIRE(values.size() == 2);
|
||||
CHECK(values[0] == 1);
|
||||
CHECK(values[1] == 2);
|
||||
|
||||
whenAllCompleted = true;
|
||||
}(),
|
||||
[&]() -> cppcoro::task<>
|
||||
{
|
||||
CHECK(!whenAllCompleted);
|
||||
event2.set();
|
||||
CHECK(!whenAllCompleted);
|
||||
event1.set();
|
||||
CHECK(whenAllCompleted);
|
||||
co_return;
|
||||
}()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("when_all() with vector<task<T>>")
|
||||
|
@ -268,48 +274,51 @@ TEST_CASE("when_all() with vector<shared_task<T>>")
|
|||
check_when_all_vector_of_task_value<cppcoro::shared_task>();
|
||||
}
|
||||
|
||||
template<template<typename T> class TASK>
|
||||
void check_when_all_vector_of_task_reference()
|
||||
namespace
|
||||
{
|
||||
cppcoro::async_manual_reset_event event1;
|
||||
cppcoro::async_manual_reset_event event2;
|
||||
|
||||
int value1 = 1;
|
||||
int value2 = 2;
|
||||
|
||||
auto makeTask = [](cppcoro::async_manual_reset_event& event, int& value) -> TASK<int&>
|
||||
template<template<typename T> class TASK>
|
||||
void check_when_all_vector_of_task_reference()
|
||||
{
|
||||
co_await event;
|
||||
co_return value;
|
||||
};
|
||||
cppcoro::async_manual_reset_event event1;
|
||||
cppcoro::async_manual_reset_event event2;
|
||||
|
||||
bool whenAllComplete = false;
|
||||
int value1 = 1;
|
||||
int value2 = 2;
|
||||
|
||||
cppcoro::sync_wait(cppcoro::when_all_ready(
|
||||
[&]() -> cppcoro::task<>
|
||||
{
|
||||
std::vector<TASK<int&>> tasks;
|
||||
tasks.emplace_back(makeTask(event1, value1));
|
||||
tasks.emplace_back(makeTask(event2, value2));
|
||||
auto makeTask = [](cppcoro::async_manual_reset_event& event, int& value) -> TASK<int&>
|
||||
{
|
||||
co_await event;
|
||||
co_return value;
|
||||
};
|
||||
|
||||
auto whenAllTask = cppcoro::when_all(std::move(tasks));
|
||||
bool whenAllComplete = false;
|
||||
|
||||
std::vector<std::reference_wrapper<int>>& values = co_await whenAllTask;
|
||||
REQUIRE(values.size() == 2);
|
||||
CHECK(&values[0].get() == &value1);
|
||||
CHECK(&values[1].get() == &value2);
|
||||
cppcoro::sync_wait(cppcoro::when_all_ready(
|
||||
[&]() -> cppcoro::task<>
|
||||
{
|
||||
std::vector<TASK<int&>> tasks;
|
||||
tasks.emplace_back(makeTask(event1, value1));
|
||||
tasks.emplace_back(makeTask(event2, value2));
|
||||
|
||||
whenAllComplete = true;
|
||||
}(),
|
||||
[&]() -> cppcoro::task<>
|
||||
{
|
||||
CHECK(!whenAllComplete);
|
||||
event2.set();
|
||||
CHECK(!whenAllComplete);
|
||||
event1.set();
|
||||
CHECK(whenAllComplete);
|
||||
co_return;
|
||||
}()));
|
||||
auto whenAllTask = cppcoro::when_all(std::move(tasks));
|
||||
|
||||
std::vector<std::reference_wrapper<int>>& values = co_await whenAllTask;
|
||||
REQUIRE(values.size() == 2);
|
||||
CHECK(&values[0].get() == &value1);
|
||||
CHECK(&values[1].get() == &value2);
|
||||
|
||||
whenAllComplete = true;
|
||||
}(),
|
||||
[&]() -> cppcoro::task<>
|
||||
{
|
||||
CHECK(!whenAllComplete);
|
||||
event2.set();
|
||||
CHECK(!whenAllComplete);
|
||||
event1.set();
|
||||
CHECK(whenAllComplete);
|
||||
co_return;
|
||||
}()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("when_all() with vector<task<T&>>")
|
||||
|
|
Loading…
Reference in a new issue