complete ipc send & recv; prepare ipc::channel; add ipc ut (basic test); add ut suit name;

This commit is contained in:
mutouyun 2018-11-30 17:32:09 +08:00
parent c8e81e2794
commit 85bb05bb52
9 changed files with 139 additions and 24 deletions

View File

@ -1,6 +1,7 @@
TEMPLATE = app
QT += core testlib
QT -= gui
CONFIG += console c++14
CONFIG -= app_bundle
@ -17,6 +18,7 @@ HEADERS += \
SOURCES += \
../test/main.cpp \
../test/test_shm.cpp \
../test/test_circ.cpp
../test/test_circ.cpp \
../test/test_ipc.cpp
LIBS += -L$${DESTDIR} -lipc

View File

@ -65,7 +65,7 @@ private:
}
static ui_t index_of(uc_t c) {
return static_cast<ui_t>(c & std::numeric_limits<ui_t>::max());
return static_cast<ui_t>(c);
}
ui_t index_of(elem_t* el) {
@ -96,7 +96,7 @@ public:
while (lc_.exchange(1, std::memory_order_acquire)) {
std::this_thread::yield();
}
elem_t* el = elem(wt_.load(std::memory_order_relaxed));
elem_t* el = elem(index_of(wt_.load(std::memory_order_relaxed)));
// check all consumers have finished reading
while(1) {
std::uint32_t expected = 0;

View File

@ -13,7 +13,24 @@ using shm::handle_t;
IPC_EXPORT handle_t connect (std::string const & name);
IPC_EXPORT void disconnect(handle_t h);
IPC_EXPORT bool send(handle_t h, byte_t* data, int size);
IPC_EXPORT bool send(handle_t h, void* data, int size);
IPC_EXPORT std::vector<byte_t> recv(handle_t h);
class channel_;
class IPC_EXPORT channel {
public:
channel(void);
channel(std::string const & name);
channel(channel&& rhs);
~channel(void);
void swap(channel& rhs);
channel& operator=(channel rhs);
private:
friend class channel_;
channel_* p_;
};
} // namespace ipc

View File

@ -3,6 +3,7 @@
#include <type_traits>
#include <cstring>
#include <algorithm>
#include <utility>
#include "ipc.h"
#include "circ_queue.h"
@ -15,6 +16,7 @@ using data_t = byte_t[data_length];
struct msg_t {
int remain_;
unsigned id_;
data_t data_;
};
@ -67,7 +69,7 @@ void disconnect(handle_t h) {
h2q__.erase(it);
}
bool send(handle_t h, byte_t* data, int size) {
bool send(handle_t h, void* data, int size) {
if (data == nullptr) {
return false;
}
@ -78,51 +80,91 @@ bool send(handle_t h, byte_t* data, int size) {
if (queue == nullptr) {
return false;
}
queue_t drop_box { queue->elems() };
static unsigned msg_id = 0;
++msg_id; // calc a new message id
int offset = 0;
for (int i = 0; i < (size / static_cast<int>(data_length)); ++i, offset += data_length) {
msg_t msg {
size - offset - static_cast<int>(data_length),
{ 0 }
msg_id, { 0 }
};
std::memcpy(msg.data_, data + offset, data_length);
drop_box.push(msg);
std::memcpy(msg.data_, static_cast<byte_t*>(data) + offset, data_length);
queue->push(msg);
}
int remain = size - offset;
if (remain > 0) {
msg_t msg { remain - static_cast<int>(data_length), { 0 } };
std::memcpy(msg.data_, data + offset, static_cast<std::size_t>(remain));
drop_box.push(msg);
msg_t msg {
remain - static_cast<int>(data_length),
msg_id, { 0 }
};
std::memcpy(msg.data_, static_cast<byte_t*>(data) + offset,
static_cast<std::size_t>(remain));
queue->push(msg);
}
return true;
}
std::vector<byte_t> recv(handle_t h) {
std::vector<byte_t> all;
auto queue = queue_of(h);
if (queue == nullptr) {
return all;
return {};
}
if (!queue->connected()) {
queue->connect();
}
static thread_local std::unordered_map<int, std::vector<byte_t>> all;
do {
auto msg = queue->pop();
auto last_size = all.size();
// here comes a new message
auto& cache = all[msg.id_]; // find the cache using message id
auto last_size = cache.size();
if (msg.remain_ > 0) {
all.resize(last_size + data_length);
std::memcpy(all.data() + last_size, msg.data_, data_length);
cache.resize(last_size + data_length);
std::memcpy(cache.data() + last_size, msg.data_, data_length);
}
else {
// remain_ is minus & abs(remain_) < data_length
std::size_t remain = static_cast<std::size_t>(
static_cast<int>(data_length) + msg.remain_);
all.resize(last_size + remain);
std::memcpy(all.data() + last_size, msg.data_, remain);
break;
cache.resize(last_size + remain);
std::memcpy(cache.data() + last_size, msg.data_, remain);
// finish this message, erase it from cache
auto ret { std::move(cache) };
all.erase(msg.id_);
return std::move(ret);
}
} while(1);
return all;
}
class channel_ {
public:
};
channel::channel(void)
: p_(new channel_) {
}
channel::channel(std::string const & /*name*/)
: channel() {
}
channel::channel(channel&& rhs)
: channel() {
swap(rhs);
}
channel::~channel(void) {
delete p_;
}
void channel::swap(channel& rhs) {
std::swap(p_, rhs.p_);
}
channel& channel::operator=(channel rhs) {
swap(rhs);
return *this;
}
} // namespace ipc

View File

@ -1,6 +1,8 @@
#include <QCoreApplication>
#include <QObject>
#include <QVector>
#include <QString>
#include <QDebug>
#include "test.h"
@ -18,6 +20,14 @@ TestSuite::TestSuite(void) {
_.suites_ << this;
}
const char* TestSuite::name(void) const {
return "";
}
void TestSuite::initTestCase(void) {
qDebug() << QString("#### Start: %1 ####").arg(name());
}
int main(int argc, char* argv[]) {
QCoreApplication app(argc, argv);
Q_UNUSED(app)

View File

@ -8,4 +8,10 @@ class TestSuite : public QObject
public:
explicit TestSuite(void);
protected:
virtual const char* name(void) const;
protected slots:
virtual void initTestCase(void);
};

View File

@ -9,14 +9,18 @@
#include "circ_elem_array.h"
#include "circ_queue.h"
#include "test.h"
#include "stopwatch.hpp"
#include "test.h"
namespace {
class Unit : public TestSuite {
Q_OBJECT
const char* name(void) const {
return "test_circ";
}
private slots:
void initTestCase(void);
void cleanupTestCase(void);
@ -36,6 +40,7 @@ using cq_t = ipc::circ::elem_array<12>;
cq_t* cq__;
void Unit::initTestCase(void) {
TestSuite::initTestCase();
cq__ = new cq_t;
}

29
test/test_ipc.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "ipc.h"
#include "test.h"
namespace {
class Unit : public TestSuite {
Q_OBJECT
const char* name(void) const {
return "test_ipc";
}
private slots:
void test_send_recv(void);
} unit__;
#include "test_ipc.moc"
void Unit::test_send_recv(void) {
auto h = ipc::connect("my-ipc");
QVERIFY(h != nullptr);
char data[] = "hello ipc!";
QVERIFY(ipc::send(h, data, sizeof(data)));
auto got = ipc::recv(h);
QCOMPARE((char*)got.data(), data);
ipc::disconnect(h);
}
} // internal-linkage

View File

@ -12,6 +12,10 @@ namespace {
class Unit : public TestSuite {
Q_OBJECT
const char* name(void) const {
return "test_shm";
}
private slots:
void test_acquire(void);
void test_release(void);