feat: added tests to check consumer resilience against corrupted data. All tests pased

This commit is contained in:
unai_71 2026-03-10 19:55:47 +00:00
parent b062dddff2
commit 2fe983d288

View File

@ -1,7 +1,11 @@
#include <gtest/gtest.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <QCoreApplication>
#include <QSignalSpy>
#include <cstring>
#include "Consumer.hpp"
#include "UnixIpcBridge.hpp"
@ -118,3 +122,94 @@ TEST(ConsumerThreadTest, StopsCleanlyWhenNeverStarted)
// stop() on a consumer that was never started must not crash
consumer.stop();
}
// ---------------------------------------------------------------------------
// Requirement 2: Consumer receiving corrupted data (non-numeric)
// ---------------------------------------------------------------------------
/// Helper: raw-connect to a UNIX socket and send arbitrary bytes.
static void send_raw_bytes(const std::string& path, const void* data,
size_t len)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT_GE(fd, 0);
struct sockaddr_un addr = {};
addr.sun_family = AF_UNIX;
std::strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1);
ASSERT_EQ(
connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)), 0);
if (len > 0)
{
::send(fd, data, len, 0);
}
close(fd);
}
TEST(ConsumerThreadTest, DropsCorruptedShortMessage)
{
const std::string sock = "/tmp/test_ct_corrupt_short.sock";
ConsumerThread consumer(sock);
QSignalSpy spy(&consumer, &ConsumerThread::valueReceived);
consumer.start();
// Send only 2 bytes instead of sizeof(int)==4 — corrupted / partial message
uint16_t garbage = 0xBEEF;
send_raw_bytes(sock, &garbage, sizeof(garbage));
// Give the consumer time to process (or not)
spy.wait(500);
consumer.stop();
// No signal should have been emitted
EXPECT_EQ(spy.count(), 0);
}
TEST(ConsumerThreadTest, DropsEmptyConnection)
{
const std::string sock = "/tmp/test_ct_corrupt_empty.sock";
ConsumerThread consumer(sock);
QSignalSpy spy(&consumer, &ConsumerThread::valueReceived);
consumer.start();
// Connect and immediately close — zero bytes sent
send_raw_bytes(sock, nullptr, 0);
spy.wait(500);
consumer.stop();
EXPECT_EQ(spy.count(), 0);
}
TEST(ConsumerThreadTest, SurvivesCorruptedThenReceivesValid)
{
const std::string sock = "/tmp/test_ct_corrupt_then_valid.sock";
ConsumerThread consumer(sock);
QSignalSpy spy(&consumer, &ConsumerThread::valueReceived);
consumer.start();
// First: send corrupted (1 byte)
uint8_t one_byte = 0xFF;
send_raw_bytes(sock, &one_byte, sizeof(one_byte));
std::this_thread::sleep_for(std::chrono::milliseconds(50));
// Then: send a valid int via the normal bridge
UnixIpcBridge bridge(sock);
bridge.send(777);
// Wait for the valid signal
for (int attempt = 0; spy.count() < 1 && attempt < 20; ++attempt)
{
spy.wait(100);
}
consumer.stop();
// The corrupted message must have been dropped, valid one received
ASSERT_EQ(spy.count(), 1);
EXPECT_EQ(spy.at(0).at(0).toInt(), 777);
}