Skip to content

Commit

Permalink
iouring: fix the IoUringImpl tests for latest kernel (envoyproxy#33833)
Browse files Browse the repository at this point in the history
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: Ryan Northey <ryan@synca.io>
  • Loading branch information
soulxu authored and phlax committed May 2, 2024
1 parent c2d05b9 commit 2bb8098
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 30 deletions.
13 changes: 3 additions & 10 deletions test/common/io/BUILD
Expand Up @@ -10,25 +10,18 @@ envoy_package()

envoy_cc_test(
name = "io_uring_impl_test",
srcs = select({
"//bazel:linux_x86_64": ["io_uring_impl_test.cc"],
"//conditions:default": [],
}),
srcs = ["io_uring_impl_test.cc"],
tags = [
"nocompdb",
"skip_on_windows",
],
deps = [
"//source/common/io:io_uring_impl_lib",
"//source/common/network:address_lib",
"//test/mocks/io:io_mocks",
"//test/test_common:environment_lib",
"//test/test_common:utility_lib",
] + select({
"//bazel:linux": [
"//source/common/io:io_uring_impl_lib",
],
"//conditions:default": [],
}),
],
)

envoy_cc_test(
Expand Down
46 changes: 26 additions & 20 deletions test/common/io/io_uring_impl_test.cc
@@ -1,3 +1,5 @@
#include <functional>

#include "source/common/io/io_uring_impl.h"
#include "source/common/network/address_impl.h"

Expand All @@ -21,6 +23,8 @@ class TestRequest : public Request {
MockIoUringSocket mock_io_uring_socket_;
};

using WaitConditionFunc = std::function<bool()>;

class IoUringImplTest : public ::testing::Test {
public:
IoUringImplTest() : api_(Api::createApiForTest()), should_skip_(!isIoUringSupported()) {
Expand All @@ -45,6 +49,18 @@ class IoUringImplTest : public ::testing::Test {
}
}

void waitForCondition(Event::Dispatcher& dispatcher, WaitConditionFunc condition_func,
std::chrono::milliseconds wait_timeout = TestUtility::DefaultTimeout) {
Event::TestTimeSystem::RealTimeBound bound(wait_timeout);
while (!condition_func()) {
if (!bound.withinBound()) {
RELEASE_ASSERT(0, "Timed out waiting for the condition.");
break;
}
dispatcher.run(Event::Dispatcher::RunType::NonBlock);
}
}

Api::ApiPtr api_;
IoUringPtr io_uring_{};
const bool should_skip_{};
Expand Down Expand Up @@ -105,8 +121,7 @@ TEST_P(IoUringImplParamTest, InvalidParams) {
res = io_uring_->submit();
EXPECT_EQ(res, IoUringResult::Ok);

dispatcher->run(Event::Dispatcher::RunType::NonBlock);
EXPECT_EQ(completions_nr, 2);
waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 2; });
}

TEST_F(IoUringImplTest, InjectCompletion) {
Expand Down Expand Up @@ -136,8 +151,7 @@ TEST_F(IoUringImplTest, InjectCompletion) {

file_event->activate(Event::FileReadyType::Read);

dispatcher->run(Event::Dispatcher::RunType::NonBlock);
EXPECT_EQ(completions_nr, 1);
waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 1; });
}

TEST_F(IoUringImplTest, NestInjectCompletion) {
Expand Down Expand Up @@ -177,8 +191,7 @@ TEST_F(IoUringImplTest, NestInjectCompletion) {

file_event->activate(Event::FileReadyType::Read);

dispatcher->run(Event::Dispatcher::RunType::NonBlock);
EXPECT_EQ(completions_nr, 2);
waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 2; });
}

TEST_F(IoUringImplTest, RemoveInjectCompletion) {
Expand Down Expand Up @@ -213,8 +226,7 @@ TEST_F(IoUringImplTest, RemoveInjectCompletion) {
EXPECT_EQ(-1, data2);
file_event->activate(Event::FileReadyType::Read);

dispatcher->run(Event::Dispatcher::RunType::NonBlock);
EXPECT_EQ(completions_nr, 1);
waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 1; });
}

TEST_F(IoUringImplTest, NestRemoveInjectCompletion) {
Expand Down Expand Up @@ -253,8 +265,7 @@ TEST_F(IoUringImplTest, NestRemoveInjectCompletion) {

file_event->activate(Event::FileReadyType::Read);

dispatcher->run(Event::Dispatcher::RunType::NonBlock);
EXPECT_EQ(completions_nr, 2);
waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 2; });
}

TEST_F(IoUringImplTest, RegisterEventfd) {
Expand Down Expand Up @@ -298,10 +309,8 @@ TEST_F(IoUringImplTest, PrepareReadvAllDataFitsOneChunk) {
EXPECT_STREQ(static_cast<char*>(iov.iov_base), "");
io_uring_->submit();

dispatcher->run(Event::Dispatcher::RunType::Block);

// Check that the completion callback has been actually called.
EXPECT_EQ(completions_nr, 1);
waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 1; });
// The file's content is in the read buffer now.
EXPECT_STREQ(static_cast<char*>(iov.iov_base), "test text");
}
Expand Down Expand Up @@ -361,31 +370,28 @@ TEST_F(IoUringImplTest, PrepareReadvQueueOverflow) {
res = io_uring_->submit();
EXPECT_EQ(res, IoUringResult::Ok);

waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 2; });
// Even though we haven't been notified about ops completion the buffers
// are filled already.
EXPECT_EQ(static_cast<char*>(iov1.iov_base)[0], 'a');
EXPECT_EQ(static_cast<char*>(iov1.iov_base)[1], 'b');
EXPECT_EQ(static_cast<char*>(iov2.iov_base)[0], 'c');
EXPECT_EQ(static_cast<char*>(iov2.iov_base)[1], 'd');

dispatcher->run(Event::Dispatcher::RunType::NonBlock);

// Only 2 completions are expected because the completion queue can contain
// no more than 2 entries.
EXPECT_EQ(completions_nr, 2);
waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 2; });

// Check a new event gets handled in the next dispatcher run.
res = io_uring_->prepareReadv(fd, &iov3, 1, 4, &request3);
EXPECT_EQ(res, IoUringResult::Ok);
res = io_uring_->submit();
EXPECT_EQ(res, IoUringResult::Ok);

waitForCondition(*dispatcher, [&completions_nr]() { return completions_nr == 3; });

EXPECT_EQ(static_cast<char*>(iov3.iov_base)[0], 'e');
EXPECT_EQ(static_cast<char*>(iov3.iov_base)[1], 'f');

dispatcher->run(Event::Dispatcher::RunType::NonBlock);
// Check the completion callback was called actually.
EXPECT_EQ(completions_nr, 3);
}

} // namespace
Expand Down

0 comments on commit 2bb8098

Please sign in to comment.