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:
Lewis Baker 2017-08-24 22:58:51 +09:30
parent 3d97b79294
commit 62cff52fd1
5 changed files with 172 additions and 145 deletions

View file

@ -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")
{

View file

@ -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")
{

View 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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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&>>")