Message ID | 20201224081713.41742-1-paul.elder@ideasonboard.com |
---|---|
Headers | show |
Series |
|
Related | show |
Hi Paul, Thanks for your work. On 2020-12-24 17:17:11 +0900, Paul Elder wrote: > Test the IPC functions of IPCPipeUnixSocket. > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > > --- > 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 | 237 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 239 insertions(+), 1 deletion(-) > create mode 100644 test/ipc/unixsocket_ipc.cpp > > diff --git a/test/ipc/meson.build b/test/ipc/meson.build > index 650df1d6..ecb6d022 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..827689f7 > --- /dev/null > +++ b/test/ipc/unixsocket_ipc.cpp > @@ -0,0 +1,237 @@ > +/* 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 <stdlib.h> > +#include <string.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" > + > +#define CMD_EXIT 0 > +#define CMD_GET_SYNC 1 > +#define CMD_SET_ASYNC 2 > + > +using namespace std; > +using namespace libcamera; > + > +class UnixSocketTestIPCSlave > +{ > +public: > + UnixSocketTestIPCSlave() > + : value_(1337), 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 CMD_EXIT: { > + exit_ = true; > + break; > + } > + > + case CMD_GET_SYNC: { > + 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 CMD_SET_ASYNC: { > + 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 setVal(int32_t val) > + { > + IPCMessage buf; > + tie(buf.data(), ignore) = IPADataSerializer<int32_t>::serialize(val); > + > + int ret = ipc_->sendAsync(CMD_SET_ASYNC, buf); > + if (ret < 0) { > + cerr << "Failed to call set value" << endl; > + return ret; > + } > + > + return 0; > + } > + > + int getVal() > + { > + IPCMessage buf; > + > + int ret = ipc_->sendSync(CMD_GET_SYNC, {}, &buf); > + if (ret < 0) { > + cerr << "Failed to call get value" << endl; > + return ret; > + } > + > + return IPADataSerializer<int32_t>::deserialize(buf.data()); > + } > + > + int exit() > + { > + int ret = ipc_->sendAsync(CMD_EXIT, {}); > + if (ret < 0) { > + cerr << "Failed to call exit" << endl; > + return ret; > + } > + > + return 0; > + } > + > + int run() > + { > + char selfpath[100]; nit: I think to play it safe you could use MAX_PATH here. > + memset(selfpath, 0, sizeof(selfpath)); > + int ret = readlink("/proc/self/exe", selfpath, sizeof(selfpath)); > + if (ret < 0) { > + int err = errno; > + cerr << "Failed to get path: " << strerror(err) << endl; > + return TestFail; > + } > + > + ipc_ = std::make_unique<IPCPipeUnixSocket>("", selfpath); > + if (!ipc_->isConnected()) { > + cerr << "Failed to create IPCPipe" << endl; > + return TestFail; > + } > + > + ret = getVal(); > + if (ret < 0) { > + cerr << "Failed to get initial value: " << strerror(-ret) << endl; > + return TestFail; > + } I would drop this < 0 check as getVal() already prints an error in that case. > + if (ret != 1337) { > + cerr << "Wrong inital value, expected 1337, got " << ret << endl; > + return TestFail; > + } > + > + ret = setVal(9001); > + if (ret < 0) { > + cerr << "Failed to set value: " << strerror(-ret) << endl; > + return TestFail; > + } > + > + ret = getVal(); > + if (ret < 0) { > + cerr << "Failed to get value: " << strerror(-ret) << endl; > + return TestFail; > + } Same here. Whit this fixed, Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> > + if (ret != 9001) { > + cerr << "Wrong set value, expected 9001, got " << ret << endl; > + 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 proxy > + * master and slave. > + */ > +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(); > +} > -- > 2.27.0 > > _______________________________________________ > libcamera-devel mailing list > libcamera-devel@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel