Skip to content

Commit

Permalink
Implement PING inline tests (#413)
Browse files Browse the repository at this point in the history
This PR implements support for the PING command over the INLINE
protocol.
  • Loading branch information
danielealbano authored May 21, 2023
1 parent 104c08a commit 3ab7670
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ TestModulesRedisCommandFixture::TestModulesRedisCommandFixture() {

PROGRAM_WAIT_FOR_WORKER_RUNNING_STATUS(worker_context, true)

this->protocol_version = TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_RESP_2;

this->c = redisConnect(config_module_network_binding.host, config_module_network_binding.port);

REQUIRE(this->c != nullptr);
Expand Down Expand Up @@ -217,24 +219,45 @@ TestModulesRedisCommandFixture::~TestModulesRedisCommandFixture() {
size_t TestModulesRedisCommandFixture::build_resp_command(
char *buffer,
size_t buffer_size,
const std::vector<std::string>& arguments) {
const std::vector<std::string>& arguments) const {
size_t buffer_offset = 0;
size_t arguments_count = arguments.size();

buffer_offset += snprintf(
buffer ? buffer + buffer_offset : nullptr,
buffer ? buffer_size - buffer_offset : 0,
"*%lu\r\n",
arguments_count);
if (this->protocol_version >= TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_RESP_2) {
buffer_offset += snprintf(
buffer ? buffer + buffer_offset : nullptr,
buffer ? buffer_size - buffer_offset : 0,
"*%lu\r\n",
arguments_count);

for (const auto &value: arguments) {
char *buffer_start = buffer + buffer_offset;
buffer_offset += snprintf(
buffer ? buffer_start : nullptr,
buffer ? buffer_size - buffer_offset : 0,
"$%lu\r\n%s\r\n",
value.length(),
value.c_str());
}
} else {
bool is_first = true;
for (const auto &value: arguments) {
char *buffer_start = buffer + buffer_offset;
buffer_offset += snprintf(
buffer ? buffer_start : nullptr,
buffer ? buffer_size - buffer_offset : 0,
"%s%s",
is_first ? "" : " ",
value.c_str());

is_first = false;
}

for(const auto& value: arguments) {
char *buffer_start = buffer + buffer_offset;
buffer_offset += snprintf(
buffer ? buffer_start : nullptr,
buffer ? buffer_size - buffer_offset : 0,
"$%lu\r\n%s\r\n",
value.length(),
value.c_str());
"\r\n");
}

return buffer_offset;
Expand Down Expand Up @@ -319,18 +342,34 @@ bool TestModulesRedisCommandFixture::send_recv_resp_command_multi_recv(
// Sets up the reader
this->c->reader = redisReaderCreate();

// Prepares the command and write it to the internal buffer
redisAppendCommandArgv(
this->c,
(int)arguments.size(),
c_strs.data(),
nullptr);

// Sends the data out
int done = 0;
do {
REQUIRE(redisBufferWrite(this->c, &done) == REDIS_OK);
} while(done == 0);
if (this->protocol_version == TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_INLINE) {
size_t buffer_length = build_resp_command(nullptr, 0, arguments);
char *buffer = (char *) malloc(buffer_length + 1);
build_resp_command(buffer, buffer_length + 1, arguments);

// Sends the data out
size_t sent_data = 0;
do {
ssize_t result = send(this->c->fd, buffer + sent_data, buffer_length - sent_data, 0);

REQUIRE(result >= 0);

sent_data += result;
} while (sent_data < buffer_length);
} else {
// Prepares the command and write it to the internal buffer
redisAppendCommandArgv(
this->c,
(int)arguments.size(),
c_strs.data(),
nullptr);

// Sends the data out
int done = 0;
do {
REQUIRE(redisBufferWrite(this->c, &done) == REDIS_OK);
} while(done == 0);
}

// As the redisReaderGetReply discards the reader buffer and we need it entirely instead, the code below handles
// the receive of the data, store them in an internal buffer and passes them to the reader for processing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@
} while((WORKER_CONTEXT)->running == !(RUNNING)); \
}

enum TestModulesRedisCommandFixtureProtocol {
TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_UNKNOWN = 0,
TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_INLINE = 1,
TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_RESP_2 = 2,
TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_RESP_3 = 3,
};

class TestModulesRedisCommandFixture {
public:
TestModulesRedisCommandFixture();
~TestModulesRedisCommandFixture();
protected:
redisContext *c;
uint8_t protocol_version;

size_t buffer_send_data_len{};
char buffer_send[16 * 1024] = {0};
Expand Down Expand Up @@ -44,11 +52,6 @@ class TestModulesRedisCommandFixture {

program_context_t *program_context;

static size_t build_resp_command(
char *buffer,
size_t buffer_size,
const std::vector<std::string>& arguments);

static size_t string_replace(
char *input,
size_t input_len,
Expand All @@ -57,8 +60,10 @@ class TestModulesRedisCommandFixture {
int count,
...);

size_t send_recv_resp_command_calculate_multi_recv(
size_t expected_length) const;
size_t build_resp_command(
char *buffer,
size_t buffer_size,
const std::vector<std::string>& arguments) const;

bool send_recv_resp_command_multi_recv(
const std::vector<std::string>& arguments,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,23 @@
#pragma GCC diagnostic ignored "-Wwrite-strings"

TEST_CASE_METHOD(TestModulesRedisCommandFixture, "Redis - command - PING", "[redis][command][PING]") {
SECTION("Without value") {
SECTION("Without value - RESP") {
REQUIRE(send_recv_resp_command_text_and_validate_recv(
std::vector<std::string>{"PING"},
"+PONG\r\n"));
}

SECTION("With value") {
SECTION("With value - RESP") {
REQUIRE(send_recv_resp_command_text_and_validate_recv(
std::vector<std::string>{"PING", "a test"},
"$6\r\na test\r\n"));
}

SECTION("Without value - Inline") {
this->protocol_version = TEST_MODULES_REDIS_COMMAND_FIXTURE_PROTOCOL_INLINE;

REQUIRE(send_recv_resp_command_text_and_validate_recv(
std::vector<std::string>{"PING"},
"+PONG\r\n"));
}
}

0 comments on commit 3ab7670

Please sign in to comment.