Message ID | 20210301065226.11095-1-paul.elder@ideasonboard.com |
---|---|
Headers | show |
Series |
|
Related | show |
On Mon, Mar 01, 2021 at 03:52:25PM +0900, Paul Elder wrote: > Test the IPC functions of IPCPipeUnixSocket. > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > --- > Changes in v9: > - change cmd codes to enum > - rename setVal and getVal to setValue and getValue > - remove readlink, and use "/proc/self/exe" directly > - make the test values into consts > > No change in v8 > > Changes in v7: > - use the new sendSync/sendAsync API > - remove redundant error messages > - use PATH_MAX instead of 100 > > No change in v6 > > Changes in v5: > - rename IPAIPCUnixSocket to IPCPipeUnixSocket > - use IPCMessage > > No change in v4 > > Changes in v3: > - use readHeader, writeHeader, and eraseHeader as static class functions > of IPAIPCUnixSocket > > New in v2 > --- > test/ipc/meson.build | 3 +- > test/ipc/unixsocket_ipc.cpp | 229 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 231 insertions(+), 1 deletion(-) > create mode 100644 test/ipc/unixsocket_ipc.cpp > > diff --git a/test/ipc/meson.build b/test/ipc/meson.build > index 9f413ff6..ad47b2fe 100644 > --- a/test/ipc/meson.build > +++ b/test/ipc/meson.build > @@ -1,7 +1,8 @@ > # SPDX-License-Identifier: CC0-1.0 > > ipc_tests = [ > - ['unixsocket', 'unixsocket.cpp'], > + ['unixsocket_ipc', 'unixsocket_ipc.cpp'], > + ['unixsocket', 'unixsocket.cpp'], > ] > > foreach t : ipc_tests > diff --git a/test/ipc/unixsocket_ipc.cpp b/test/ipc/unixsocket_ipc.cpp > new file mode 100644 > index 00000000..5c9f7938 > --- /dev/null > +++ b/test/ipc/unixsocket_ipc.cpp > @@ -0,0 +1,229 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2020, Google Inc. > + * > + * unixsocket_ipc.cpp - Unix socket IPC test > + */ > + > +#include <algorithm> > +#include <fcntl.h> > +#include <iostream> > +#include <limits.h> > +#include <stdlib.h> > +#include <sys/stat.h> > +#include <sys/types.h> > +#include <sys/wait.h> > +#include <unistd.h> > + > +#include "libcamera/internal/event_dispatcher.h" > +#include "libcamera/internal/ipa_data_serializer.h" > +#include "libcamera/internal/ipc_pipe.h" > +#include "libcamera/internal/ipc_pipe_unixsocket.h" > +#include "libcamera/internal/process.h" > +#include "libcamera/internal/thread.h" > +#include "libcamera/internal/timer.h" > +#include "libcamera/internal/utils.h" > + > +#include "test.h" > + > + > +using namespace std; > +using namespace libcamera; > + > +enum cmd { You can omit the type name, or called it Cmd as we Capitalize type names. > + CmdExit = 0, > + CmdGetSync = 1, > + CmdSetAsync = 2, > +}; > + > +const int32_t initialValue = 1337; > +const int32_t changedValue = 9001; Maybe kInitialValue and kChangedValue ? > + > +class UnixSocketTestIPCSlave > +{ > +public: > + UnixSocketTestIPCSlave() > + : value_(initialValue), exitCode_(EXIT_FAILURE), exit_(false) > + { > + dispatcher_ = Thread::current()->eventDispatcher(); > + ipc_.readyRead.connect(this, &UnixSocketTestIPCSlave::readyRead); > + } > + > + int run(int fd) > + { > + if (ipc_.bind(fd)) { > + cerr << "Failed to connect to IPC channel" << endl; > + return EXIT_FAILURE; > + } > + > + while (!exit_) > + dispatcher_->processEvents(); > + > + ipc_.close(); > + > + return exitCode_; > + } > + > +private: > + void readyRead(IPCUnixSocket *ipc) > + { > + IPCUnixSocket::Payload message; > + int ret; > + > + ret = ipc->receive(&message); > + if (ret) { > + cerr << "Receive message failed: " << ret << endl; > + return; > + } > + > + IPCMessage ipcMessage(message); > + uint32_t cmd = ipcMessage.header().cmd; > + > + switch (cmd) { > + case CmdExit: { > + exit_ = true; > + break; > + } > + > + case CmdGetSync: { > + IPCMessage::Header header = { cmd, ipcMessage.header().cookie }; > + IPCMessage response(header); > + > + vector<uint8_t> buf; > + tie(buf, ignore) = IPADataSerializer<int32_t>::serialize(value_); > + response.data().insert(response.data().end(), buf.begin(), buf.end()); > + > + ret = ipc_.send(response.payload()); > + if (ret < 0) { > + cerr << "Reply failed" << endl; > + stop(ret); > + } > + break; > + } > + > + case CmdSetAsync: { > + value_ = IPADataSerializer<int32_t>::deserialize(ipcMessage.data()); > + break; > + } > + } > + } > + > + void stop(int code) > + { > + exitCode_ = code; > + exit_ = true; > + } > + > + int32_t value_; > + > + IPCUnixSocket ipc_; > + EventDispatcher *dispatcher_; > + int exitCode_; > + bool exit_; > +}; > + > +class UnixSocketTestIPC : public Test > +{ > +protected: > + int init() > + { > + return 0; > + } > + > + int setValue(int32_t val) > + { > + IPCMessage msg(CmdSetAsync); > + tie(msg.data(), ignore) = IPADataSerializer<int32_t>::serialize(val); > + > + int ret = ipc_->sendAsync(msg); > + if (ret < 0) { > + cerr << "Failed to call set value" << endl; > + return ret; > + } > + > + return 0; > + } > + > + int getValue() > + { > + IPCMessage msg(CmdGetSync); > + IPCMessage buf; > + > + int ret = ipc_->sendSync(msg, &buf); > + if (ret < 0) { > + cerr << "Failed to call get value" << endl; > + return ret; > + } > + > + return IPADataSerializer<int32_t>::deserialize(buf.data()); > + } > + > + int exit() > + { > + IPCMessage msg(CmdExit); > + > + int ret = ipc_->sendAsync(msg); > + if (ret < 0) { > + cerr << "Failed to call exit" << endl; > + return ret; > + } > + > + return 0; > + } > + > + int run() > + { > + ipc_ = std::make_unique<IPCPipeUnixSocket>("", "/proc/self/exe"); > + if (!ipc_->isConnected()) { > + cerr << "Failed to create IPCPipe" << endl; > + return TestFail; > + } > + > + int ret = getValue(); > + if (ret != initialValue) { > + cerr << "Wrong inital value, expected " << initialValue << ", got " << ret << endl; Line wrap ? > + return TestFail; > + } > + > + ret = setValue(changedValue); > + if (ret < 0) { > + cerr << "Failed to set value: " << strerror(-ret) << endl; > + return TestFail; > + } > + > + ret = getValue(); > + if (ret != changedValue) { > + cerr << "Wrong set value, expected " << changedValue << ", got " << ret << endl; Same here. > + return TestFail; > + } > + > + ret = exit(); > + if (ret < 0) { > + cerr << "Failed to exit: " << strerror(-ret) << endl; > + return TestFail; > + } > + > + return TestPass; > + } > + > +private: > + ProcessManager processManager_; > + > + unique_ptr<IPCPipeUnixSocket> ipc_; > +}; > + > +/* > + * Can't use TEST_REGISTER() as single binary needs to act as both client and > + * server > + */ > +int main(int argc, char **argv) > +{ > + /* IPCPipeUnixSocket passes IPA module path in argv[1] */ > + if (argc == 3) { > + int ipcfd = std::stoi(argv[2]); > + UnixSocketTestIPCSlave slave; > + return slave.run(ipcfd); > + } > + > + return UnixSocketTestIPC().execute(); > +}