[{"id":15379,"web_url":"https://patchwork.libcamera.org/comment/15379/","msgid":"<YD2M/mUiazvSM4VK@pendragon.ideasonboard.com>","date":"2021-03-02T00:55:26","subject":"Re: [libcamera-devel] [PATCH v9 2/3] tests: Add test for\n\tIPCPipeUnixSocket","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Mon, Mar 01, 2021 at 03:52:25PM +0900, Paul Elder wrote:\n> Test the IPC functions of IPCPipeUnixSocket.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> \n> ---\n> Changes in v9:\n> - change cmd codes to enum\n> - rename setVal and getVal to setValue and getValue\n> - remove readlink, and use \"/proc/self/exe\" directly\n> - make the test values into consts\n> \n> No change in v8\n> \n> Changes in v7:\n> - use the new sendSync/sendAsync API\n> - remove redundant error messages\n> - use PATH_MAX instead of 100\n> \n> No change in v6\n> \n> Changes in v5:\n> - rename IPAIPCUnixSocket to IPCPipeUnixSocket\n> - use IPCMessage\n> \n> No change in v4\n> \n> Changes in v3:\n> - use readHeader, writeHeader, and eraseHeader as static class functions\n>   of IPAIPCUnixSocket\n> \n> New in v2\n> ---\n>  test/ipc/meson.build        |   3 +-\n>  test/ipc/unixsocket_ipc.cpp | 229 ++++++++++++++++++++++++++++++++++++\n>  2 files changed, 231 insertions(+), 1 deletion(-)\n>  create mode 100644 test/ipc/unixsocket_ipc.cpp\n> \n> diff --git a/test/ipc/meson.build b/test/ipc/meson.build\n> index 9f413ff6..ad47b2fe 100644\n> --- a/test/ipc/meson.build\n> +++ b/test/ipc/meson.build\n> @@ -1,7 +1,8 @@\n>  # SPDX-License-Identifier: CC0-1.0\n>  \n>  ipc_tests = [\n> -    ['unixsocket',   'unixsocket.cpp'],\n> +    ['unixsocket_ipc', 'unixsocket_ipc.cpp'],\n> +    ['unixsocket',     'unixsocket.cpp'],\n>  ]\n>  \n>  foreach t : ipc_tests\n> diff --git a/test/ipc/unixsocket_ipc.cpp b/test/ipc/unixsocket_ipc.cpp\n> new file mode 100644\n> index 00000000..5c9f7938\n> --- /dev/null\n> +++ b/test/ipc/unixsocket_ipc.cpp\n> @@ -0,0 +1,229 @@\n> +/* SPDX-License-Identifier: GPL-2.0-or-later */\n> +/*\n> + * Copyright (C) 2020, Google Inc.\n> + *\n> + * unixsocket_ipc.cpp - Unix socket IPC test\n> + */\n> +\n> +#include <algorithm>\n> +#include <fcntl.h>\n> +#include <iostream>\n> +#include <limits.h>\n> +#include <stdlib.h>\n> +#include <sys/stat.h>\n> +#include <sys/types.h>\n> +#include <sys/wait.h>\n> +#include <unistd.h>\n> +\n> +#include \"libcamera/internal/event_dispatcher.h\"\n> +#include \"libcamera/internal/ipa_data_serializer.h\"\n> +#include \"libcamera/internal/ipc_pipe.h\"\n> +#include \"libcamera/internal/ipc_pipe_unixsocket.h\"\n> +#include \"libcamera/internal/process.h\"\n> +#include \"libcamera/internal/thread.h\"\n> +#include \"libcamera/internal/timer.h\"\n> +#include \"libcamera/internal/utils.h\"\n> +\n> +#include \"test.h\"\n> +\n> +\n> +using namespace std;\n> +using namespace libcamera;\n> +\n> +enum cmd {\n\nYou can omit the type name, or called it Cmd as we Capitalize type\nnames.\n\n> +\tCmdExit = 0,\n> +\tCmdGetSync = 1,\n> +\tCmdSetAsync = 2,\n> +};\n> +\n> +const int32_t initialValue = 1337;\n> +const int32_t changedValue = 9001;\n\nMaybe kInitialValue and kChangedValue ?\n\n> +\n> +class UnixSocketTestIPCSlave\n> +{\n> +public:\n> +\tUnixSocketTestIPCSlave()\n> +\t\t: value_(initialValue), exitCode_(EXIT_FAILURE), exit_(false)\n> +\t{\n> +\t\tdispatcher_ = Thread::current()->eventDispatcher();\n> +\t\tipc_.readyRead.connect(this, &UnixSocketTestIPCSlave::readyRead);\n> +\t}\n> +\n> +\tint run(int fd)\n> +\t{\n> +\t\tif (ipc_.bind(fd)) {\n> +\t\t\tcerr << \"Failed to connect to IPC channel\" << endl;\n> +\t\t\treturn EXIT_FAILURE;\n> +\t\t}\n> +\n> +\t\twhile (!exit_)\n> +\t\t\tdispatcher_->processEvents();\n> +\n> +\t\tipc_.close();\n> +\n> +\t\treturn exitCode_;\n> +\t}\n> +\n> +private:\n> +\tvoid readyRead(IPCUnixSocket *ipc)\n> +\t{\n> +\t\tIPCUnixSocket::Payload message;\n> +\t\tint ret;\n> +\n> +\t\tret = ipc->receive(&message);\n> +\t\tif (ret) {\n> +\t\t\tcerr << \"Receive message failed: \" << ret << endl;\n> +\t\t\treturn;\n> +\t\t}\n> +\n> +\t\tIPCMessage ipcMessage(message);\n> +\t\tuint32_t cmd = ipcMessage.header().cmd;\n> +\n> +\t\tswitch (cmd) {\n> +\t\tcase CmdExit: {\n> +\t\t\texit_ = true;\n> +\t\t\tbreak;\n> +\t\t}\n> +\n> +\t\tcase CmdGetSync: {\n> +\t\t\tIPCMessage::Header header = { cmd, ipcMessage.header().cookie };\n> +\t\t\tIPCMessage response(header);\n> +\n> +\t\t\tvector<uint8_t> buf;\n> +\t\t\ttie(buf, ignore) = IPADataSerializer<int32_t>::serialize(value_);\n> +\t\t\tresponse.data().insert(response.data().end(), buf.begin(), buf.end());\n> +\n> +\t\t\tret = ipc_.send(response.payload());\n> +\t\t\tif (ret < 0) {\n> +\t\t\t\tcerr << \"Reply failed\" << endl;\n> +\t\t\t\tstop(ret);\n> +\t\t\t}\n> +\t\t\tbreak;\n> +\t\t}\n> +\n> +\t\tcase CmdSetAsync: {\n> +\t\t\tvalue_ = IPADataSerializer<int32_t>::deserialize(ipcMessage.data());\n> +\t\t\tbreak;\n> +\t\t}\n> +\t\t}\n> +\t}\n> +\n> +\tvoid stop(int code)\n> +\t{\n> +\t\texitCode_ = code;\n> +\t\texit_ = true;\n> +\t}\n> +\n> +\tint32_t value_;\n> +\n> +\tIPCUnixSocket ipc_;\n> +\tEventDispatcher *dispatcher_;\n> +\tint exitCode_;\n> +\tbool exit_;\n> +};\n> +\n> +class UnixSocketTestIPC : public Test\n> +{\n> +protected:\n> +\tint init()\n> +\t{\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tint setValue(int32_t val)\n> +\t{\n> +\t\tIPCMessage msg(CmdSetAsync);\n> +\t\ttie(msg.data(), ignore) = IPADataSerializer<int32_t>::serialize(val);\n> +\n> +\t\tint ret = ipc_->sendAsync(msg);\n> +\t\tif (ret < 0) {\n> +\t\t\tcerr << \"Failed to call set value\" << endl;\n> +\t\t\treturn ret;\n> +\t\t}\n> +\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tint getValue()\n> +\t{\n> +\t\tIPCMessage msg(CmdGetSync);\n> +\t\tIPCMessage buf;\n> +\n> +\t\tint ret = ipc_->sendSync(msg, &buf);\n> +\t\tif (ret < 0) {\n> +\t\t\tcerr << \"Failed to call get value\" << endl;\n> +\t\t\treturn ret;\n> +\t\t}\n> +\n> +\t\treturn IPADataSerializer<int32_t>::deserialize(buf.data());\n> +\t}\n> +\n> +\tint exit()\n> +\t{\n> +\t\tIPCMessage msg(CmdExit);\n> +\n> +\t\tint ret = ipc_->sendAsync(msg);\n> +\t\tif (ret < 0) {\n> +\t\t\tcerr << \"Failed to call exit\" << endl;\n> +\t\t\treturn ret;\n> +\t\t}\n> +\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tint run()\n> +\t{\n> +\t\tipc_ = std::make_unique<IPCPipeUnixSocket>(\"\", \"/proc/self/exe\");\n> +\t\tif (!ipc_->isConnected()) {\n> +\t\t\tcerr << \"Failed to create IPCPipe\" << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tint ret = getValue();\n> +\t\tif (ret != initialValue) {\n> +\t\t\tcerr << \"Wrong inital value, expected \" << initialValue << \", got \" << ret << endl;\n\nLine wrap ?\n\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tret = setValue(changedValue);\n> +\t\tif (ret < 0) {\n> +\t\t\tcerr << \"Failed to set value: \" << strerror(-ret) << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tret = getValue();\n> +\t\tif (ret != changedValue) {\n> +\t\t\tcerr << \"Wrong set value, expected \" << changedValue << \", got \" << ret << endl;\n\nSame here.\n\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tret = exit();\n> +\t\tif (ret < 0) {\n> +\t\t\tcerr << \"Failed to exit: \" << strerror(-ret) << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\treturn TestPass;\n> +\t}\n> +\n> +private:\n> +\tProcessManager processManager_;\n> +\n> +\tunique_ptr<IPCPipeUnixSocket> ipc_;\n> +};\n> +\n> +/*\n> + * Can't use TEST_REGISTER() as single binary needs to act as both client and\n> + * server\n> + */\n> +int main(int argc, char **argv)\n> +{\n> +\t/* IPCPipeUnixSocket passes IPA module path in argv[1] */\n> +\tif (argc == 3) {\n> +\t\tint ipcfd = std::stoi(argv[2]);\n> +\t\tUnixSocketTestIPCSlave slave;\n> +\t\treturn slave.run(ipcfd);\n> +\t}\n> +\n> +\treturn UnixSocketTestIPC().execute();\n> +}","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 13A23BD1F1\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  2 Mar 2021 00:55:56 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D1E6468A8D;\n\tTue,  2 Mar 2021 01:55:55 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D139560522\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  2 Mar 2021 01:55:54 +0100 (CET)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 6A53F6F3;\n\tTue,  2 Mar 2021 01:55:54 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"SWCCeTlD\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1614646554;\n\tbh=WOmUElt2tr1nQ7d2PH9Y57vwLOsQ8SP30bu+Ff5TY2Q=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=SWCCeTlD9KkAozJX9ui/KgC0UXpT4Yve866DUocQOX87GLTduBEDmm7QyafUntsLD\n\tRWn7zxs9EF6pDfAbTbQWOFVQpXvvkdA9wwHll4EvF1R93qFr4+w1wauc1xR4sYf0sb\n\t0c5JpXG14pqRHnJjqi3gfGtJ8sm3yo1j25X43Gvw=","Date":"Tue, 2 Mar 2021 02:55:26 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Message-ID":"<YD2M/mUiazvSM4VK@pendragon.ideasonboard.com>","References":"<20210301065226.11095-1-paul.elder@ideasonboard.com>\n\t<20210301065226.11095-3-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20210301065226.11095-3-paul.elder@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v9 2/3] tests: Add test for\n\tIPCPipeUnixSocket","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]