Reworked test.
diff --git a/asio/src/tests/unit/channel.cpp b/asio/src/tests/unit/channel.cpp
index 013d6bc..0f73d02 100644
--- a/asio/src/tests/unit/channel.cpp
+++ b/asio/src/tests/unit/channel.cpp
@@ -18,6 +18,7 @@
#include "asio/io_service.hpp"
#include "unit_test.hpp"
+#include <list>
#if defined(ASIO_HAS_BOOST_BIND)
# include <boost/bind.hpp>
@@ -48,54 +49,328 @@
*out_value = value;
}
-//------------------------------------------------------------------------------
-// channel of int, 0-sized buffer
-
-void int_buffer0_sync_sync_test()
+void sync_put_sync_get_test(const std::size_t capacity)
{
asio::io_service io_service;
- asio::channel<int> ch(io_service, 0);
+ asio::channel<int> ch(io_service, capacity);
asio::error_code ec;
ASIO_CHECK(ch.is_open());
- ASIO_CHECK(!ch.ready());
- ch.put(1, ec);
- ASIO_CHECK(ec == asio::error::would_block);
- ASIO_CHECK(!ch.ready());
+ // put / get
- int value = ch.get(ec);
- ASIO_CHECK(ec == asio::error::would_block);
- ASIO_CHECK(value == 0);
- ASIO_CHECK(!ch.ready());
+ for (std::size_t max_puts = 0; max_puts < capacity * 2 + 1; ++max_puts)
+ {
+ const std::size_t buffered_puts = (std::min)(max_puts, capacity);
- ch.close();
- ASIO_CHECK(!ch.is_open());
- ASIO_CHECK(ch.ready());
+ for (std::size_t partial_puts = 0;
+ partial_puts < buffered_puts; ++partial_puts)
+ {
+ for (std::size_t partial_gets = 0;
+ partial_gets + 1 < partial_puts; ++partial_gets)
+ {
+ std::size_t puts = 0;
+ std::size_t gets = 0;
- ch.put(1, ec);
- ASIO_CHECK(ec == asio::error::broken_pipe);
- ASIO_CHECK(ch.ready());
+ ASIO_CHECK(!ch.ready());
- value = ch.get(ec);
- ASIO_CHECK(ec == asio::error::broken_pipe);
- ASIO_CHECK(value == 0);
- ASIO_CHECK(ch.ready());
+ for (; puts < partial_puts; ++puts)
+ {
+ ch.put(static_cast<int>(puts), ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(ch.ready());
+ }
- ch.reset();
- ASIO_CHECK(ch.is_open());
- ASIO_CHECK(!ch.ready());
+ for (; gets < partial_gets; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(value == static_cast<int>(gets));
+ }
- ch.put(1, ec);
- ASIO_CHECK(ec == asio::error::would_block);
- ASIO_CHECK(!ch.ready());
+ for (; puts < buffered_puts + partial_gets; ++puts)
+ {
+ ch.put(static_cast<int>(puts), ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(ch.ready());
+ }
- value = ch.get(ec);
- ASIO_CHECK(ec == asio::error::would_block);
- ASIO_CHECK(value == 0);
- ASIO_CHECK(!ch.ready());
+ for (; puts < max_puts + partial_gets; ++puts)
+ {
+ ch.put(static_cast<int>(puts), ec);
+ ASIO_CHECK(ec == asio::error::would_block);
+ if (capacity > 0)
+ ASIO_CHECK(ch.ready());
+ else
+ ASIO_CHECK(!ch.ready());
+ }
+
+ for (; gets < buffered_puts + partial_gets; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(value == static_cast<int>(gets));
+ }
+
+ for (; gets < max_puts + partial_gets + 1; ++gets)
+ {
+ ASIO_CHECK(!ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(ec == asio::error::would_block);
+ ASIO_CHECK(value == 0);
+ }
+ }
+ }
+ }
+
+ // put / close / put / get
+
+ for (std::size_t max_puts = 0;
+ max_puts < capacity * 2 + 1; ++max_puts)
+ {
+ const std::size_t buffered_puts = (std::min)(max_puts, capacity);
+ std::size_t puts = 0;
+ std::size_t gets = 0;
+
+ ASIO_CHECK(!ch.ready());
+
+ for (; puts < buffered_puts; ++puts)
+ {
+ ch.put(static_cast<int>(puts), ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(ch.ready());
+ }
+
+ for (; puts < max_puts; ++puts)
+ {
+ ch.put(static_cast<int>(puts), ec);
+ ASIO_CHECK(ec == asio::error::would_block);
+ if (capacity > 0)
+ ASIO_CHECK(ch.ready());
+ else
+ ASIO_CHECK(!ch.ready());
+ }
+
+ ch.close();
+ ASIO_CHECK(!ch.is_open());
+ ASIO_CHECK(ch.ready());
+
+ ch.put(1, ec);
+ ASIO_CHECK(ec == asio::error::broken_pipe);
+ ASIO_CHECK(ch.ready());
+
+ for (; gets < buffered_puts; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(value == static_cast<int>(gets));
+ }
+
+ for (; gets < max_puts + 1; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(ec == asio::error::broken_pipe);
+ if (ec != asio::error::broken_pipe)
+ ASIO_CHECK(value == 0);
+ }
+
+ ch.reset();
+ ASIO_CHECK(ch.is_open());
+ ASIO_CHECK(!ch.ready());
+ }
}
+void async_put_sync_get_test(const std::size_t capacity)
+{
+ asio::io_service io_service;
+ asio::channel<int> ch(io_service, capacity);
+ asio::error_code ec;
+
+ ASIO_CHECK(ch.is_open());
+
+ // put / get
+
+ for (std::size_t max_puts = 0; max_puts < capacity * 2 + 1; ++max_puts)
+ {
+ const std::size_t buffered_puts = (std::min)(max_puts, capacity);
+
+ for (std::size_t partial_puts = 0;
+ partial_puts < buffered_puts; ++partial_puts)
+ {
+ for (std::size_t partial_gets = 0;
+ partial_gets + 1 < partial_puts; ++partial_gets)
+ {
+ std::size_t puts = 0;
+ std::size_t gets = 0;
+ std::list<asio::error_code> put_ecs;
+
+ ASIO_CHECK(!ch.ready());
+
+ for (; puts < partial_puts; ++puts)
+ {
+ put_ecs.push_back(asio::error::would_block);
+ ch.async_put(static_cast<int>(puts),
+ bindns::bind(&put_handler, _1, &put_ecs.back()));
+ ASIO_CHECK(put_ecs.back() == asio::error::would_block);
+ ASIO_CHECK(ch.ready());
+ }
+
+ io_service.reset();
+ io_service.run();
+ while (!put_ecs.empty())
+ {
+ ASIO_CHECK(!put_ecs.front());
+ put_ecs.pop_front();
+ }
+
+ for (; gets < partial_gets; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(value == static_cast<int>(gets));
+ }
+
+ for (; puts < buffered_puts + partial_gets; ++puts)
+ {
+ put_ecs.push_back(asio::error::would_block);
+ ch.async_put(static_cast<int>(puts),
+ bindns::bind(&put_handler, _1, &put_ecs.back()));
+ ASIO_CHECK(put_ecs.back() == asio::error::would_block);
+ ASIO_CHECK(ch.ready());
+ }
+
+ io_service.reset();
+ io_service.run();
+ while (!put_ecs.empty())
+ {
+ ASIO_CHECK(!put_ecs.front());
+ put_ecs.pop_front();
+ }
+
+ for (; puts < max_puts + partial_gets; ++puts)
+ {
+ put_ecs.push_back(asio::error::would_block);
+ ch.async_put(static_cast<int>(puts),
+ bindns::bind(&put_handler, _1, &put_ecs.back()));
+ ASIO_CHECK(put_ecs.back() == asio::error::would_block);
+ ASIO_CHECK(ch.ready());
+ }
+
+ for (; gets < max_puts + partial_gets; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(value == static_cast<int>(gets));
+ }
+
+ for (; gets < max_puts + partial_gets + 1; ++gets)
+ {
+ ASIO_CHECK(!ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(ec == asio::error::would_block);
+ ASIO_CHECK(value == 0);
+ }
+
+ io_service.reset();
+ io_service.run();
+ while (!put_ecs.empty())
+ {
+ ASIO_CHECK(!put_ecs.front());
+ put_ecs.pop_front();
+ }
+ }
+ }
+ }
+
+ // put / close / put / get
+
+ for (std::size_t max_puts = 0;
+ max_puts < capacity * 2 + 1; ++max_puts)
+ {
+ const std::size_t buffered_puts = (std::min)(max_puts, capacity);
+ std::size_t puts = 0;
+ std::size_t gets = 0;
+ std::list<asio::error_code> put_ecs;
+
+ ASIO_CHECK(!ch.ready());
+
+ for (; puts < buffered_puts; ++puts)
+ {
+ put_ecs.push_back(asio::error::would_block);
+ ch.async_put(static_cast<int>(puts),
+ bindns::bind(&put_handler, _1, &put_ecs.back()));
+ ASIO_CHECK(put_ecs.back() == asio::error::would_block);
+ ASIO_CHECK(ch.ready());
+ }
+
+ io_service.reset();
+ io_service.run();
+ while (!put_ecs.empty())
+ {
+ ASIO_CHECK(!put_ecs.front());
+ put_ecs.pop_front();
+ }
+
+ for (; puts < max_puts; ++puts)
+ {
+ put_ecs.push_back(asio::error::would_block);
+ ch.async_put(static_cast<int>(puts),
+ bindns::bind(&put_handler, _1, &put_ecs.back()));
+ ASIO_CHECK(put_ecs.back() == asio::error::would_block);
+ ASIO_CHECK(ch.ready());
+ }
+
+ ch.close();
+ ASIO_CHECK(!ch.is_open());
+ ASIO_CHECK(ch.ready());
+
+ put_ecs.push_back(asio::error::would_block);
+ ch.async_put(static_cast<int>(puts),
+ bindns::bind(&put_handler, _1, &put_ecs.back()));
+ ASIO_CHECK(put_ecs.back() == asio::error::would_block);
+ ASIO_CHECK(ch.ready());
+
+ for (; gets < max_puts; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(!ec);
+ ASIO_CHECK(value == static_cast<int>(gets));
+ }
+
+ for (; gets < max_puts + 1; ++gets)
+ {
+ ASIO_CHECK(ch.ready());
+ int value = ch.get(ec);
+ ASIO_CHECK(ec == asio::error::broken_pipe);
+ if (ec != asio::error::broken_pipe)
+ ASIO_CHECK(value == 0);
+ }
+
+ io_service.reset();
+ io_service.run();
+ while (!put_ecs.empty())
+ {
+ if (put_ecs.size() > 1)
+ ASIO_CHECK(!put_ecs.front());
+ else
+ ASIO_CHECK(put_ecs.front() == asio::error::broken_pipe);
+ put_ecs.pop_front();
+ }
+
+ ch.reset();
+ ASIO_CHECK(ch.is_open());
+ ASIO_CHECK(!ch.ready());
+ }
+}
+
+#if 0
void int_buffer0_async_sync_test()
{
asio::io_service io_service;
@@ -584,15 +859,17 @@
ASIO_CHECK(ec == asio::error::would_block);
ASIO_CHECK(!ch.ready());
}
+#endif
} // namespace channel_test
+std::size_t sizes[] = { 0, 1, 2, 3, 4 };
+
ASIO_TEST_SUITE
(
"channel",
- ASIO_TEST_CASE(channel_test::int_buffer0_sync_sync_test)
- ASIO_TEST_CASE(channel_test::int_buffer0_async_sync_test)
- ASIO_TEST_CASE(channel_test::int_buffer0_sync_async_test)
- ASIO_TEST_CASE(channel_test::int_buffer0_async_async_test)
- ASIO_TEST_CASE(channel_test::void_buffer0_sync_sync_test)
+ ASIO_PARAM_TEST_CASE(
+ channel_test::sync_put_sync_get_test, sizes, sizes + 5)
+ ASIO_PARAM_TEST_CASE(
+ channel_test::async_put_sync_get_test, sizes, sizes + 5)
)
diff --git a/asio/src/tests/unit/unit_test.hpp b/asio/src/tests/unit/unit_test.hpp
index 628eaf1..419386a 100644
--- a/asio/src/tests/unit/unit_test.hpp
+++ b/asio/src/tests/unit/unit_test.hpp
@@ -66,9 +66,17 @@
test(); \
std::cout << #test << " passed" << std::endl;
+#define ASIO_PARAM_TEST_CASE(test, params_begin, params_end) \
+ for (auto i = params_begin; i != params_end; ++i) \
+ { \
+ test(*i); \
+ std::cout << #test << "(" << *i << ") passed" << std::endl; \
+ }
+
#else // defined(ASIO_STANDALONE)
#include <boost/test/unit_test.hpp>
+#include <boost/test/parameterized_test.hpp>
using boost::unit_test::test_suite;
#define ASIO_CHECK(expr) BOOST_CHECK(expr)
@@ -90,6 +98,9 @@
#define ASIO_TEST_CASE(test) \
t->add(BOOST_TEST_CASE(&test));
+#define ASIO_PARAM_TEST_CASE(test, params_begin, params_end) \
+ t->add(BOOST_PARAM_TEST_CASE(&test, (params_begin), (params_end)));
+
#endif // defined(ASIO_STANDALONE)
#if defined(ASIO_MSVC)