{"id":2313,"url":"https://patchwork.libcamera.org/api/patches/2313/?format=json","web_url":"https://patchwork.libcamera.org/patch/2313/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20191108205409.18845-18-laurent.pinchart@ideasonboard.com>","date":"2019-11-08T20:54:02","name":"[libcamera-devel,v2,17/24] test: Add control serialization test","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"3dabae508f5766011592764edfa58e4e976518b8","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/2313/mbox/","series":[{"id":568,"url":"https://patchwork.libcamera.org/api/series/568/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=568","date":"2019-11-08T20:53:45","name":"Control serialization and IPA C API","version":2,"mbox":"https://patchwork.libcamera.org/series/568/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/2313/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/2313/checks/","tags":{},"headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7F2CD61516\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri,  8 Nov 2019 21:54:28 +0100 (CET)","from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1DE17A2A;\n\tFri,  8 Nov 2019 21:54:28 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1573246468;\n\tbh=n6tFsNdq4kKSyjfbA/24/q0hZV5IBeeMjcD060i+gCY=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=AD6ISf/90phM+YR/EA5dGEpk64R9rV5h7RV9bklo+06bQB5LcSETH2tItSO4CWDZl\n\tH8MRmMyyYzLmDz2IxdEM8asxrBMs9rEf+bUBAwJcxNbUNxfWCN7Frzd/n2U6RjyzmW\n\t9XTufEXTTJ3CgPnSTOvShtKWSU0Xm8pPp6ifn5rw=","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Date":"Fri,  8 Nov 2019 22:54:02 +0200","Message-Id":"<20191108205409.18845-18-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.23.0","In-Reply-To":"<20191108205409.18845-1-laurent.pinchart@ideasonboard.com>","References":"<20191108205409.18845-1-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v2 17/24] test: Add control serialization\n\ttest","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>","X-List-Received-Date":"Fri, 08 Nov 2019 20:54:29 -0000"},"content":"From: Jacopo Mondi <jacopo@jmondi.org>\n\nAdd a test that exercises the ControlSerializer to serialize and\ndeserialize ControlInfoMap and ControlList.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n test/meson.build                             |   1 +\n test/serialization/control_serialization.cpp | 161 +++++++++++++++++++\n test/serialization/meson.build               |  11 ++\n test/serialization/serialization_test.cpp    |  89 ++++++++++\n test/serialization/serialization_test.h      |  33 ++++\n 5 files changed, 295 insertions(+)\n create mode 100644 test/serialization/control_serialization.cpp\n create mode 100644 test/serialization/meson.build\n create mode 100644 test/serialization/serialization_test.cpp\n create mode 100644 test/serialization/serialization_test.h","diff":"diff --git a/test/meson.build b/test/meson.build\nindex adb5b29e69f3..1bb2161dc05a 100644\n--- a/test/meson.build\n+++ b/test/meson.build\n@@ -8,6 +8,7 @@ subdir('log')\n subdir('media_device')\n subdir('pipeline')\n subdir('process')\n+subdir('serialization')\n subdir('stream')\n subdir('v4l2_subdevice')\n subdir('v4l2_videodevice')\ndiff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp\nnew file mode 100644\nindex 000000000000..adfb498b5bd2\n--- /dev/null\n+++ b/test/serialization/control_serialization.cpp\n@@ -0,0 +1,161 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * control_serialization.cpp - Serialize and deserialize controls\n+ */\n+\n+#include <iostream>\n+\n+#include <libcamera/camera.h>\n+#include <libcamera/control_ids.h>\n+#include <libcamera/controls.h>\n+\n+#include \"byte_stream_buffer.h\"\n+#include \"control_serializer.h\"\n+#include \"serialization_test.h\"\n+#include \"test.h\"\n+\n+using namespace std;\n+using namespace libcamera;\n+\n+class ControlSerializationTest : public SerializationTest\n+{\n+protected:\n+\tint run() override\n+\t{\n+\t\tControlSerializer serializer;\n+\t\tControlSerializer deserializer;\n+\n+\t\tstd::vector<uint8_t> infoData;\n+\t\tstd::vector<uint8_t> listData;\n+\n+\t\tsize_t size;\n+\t\tint ret;\n+\n+\t\t/* Create a control list with three controls. */\n+\t\tconst ControlInfoMap &infoMap = camera_->controls();\n+\t\tControlList list(infoMap);\n+\n+\t\tlist.set(controls::Brightness, 255);\n+\t\tlist.set(controls::Contrast, 128);\n+\t\tlist.set(controls::Saturation, 50);\n+\n+\t\t/*\n+\t\t * Serialize the control list, this should fail as the control\n+\t\t * info map hasn't been serialized.\n+\t\t */\n+\t\tsize = serializer.binarySize(list);\n+\t\tlistData.resize(size);\n+\t\tByteStreamBuffer buffer(listData.data(), listData.size());\n+\n+\t\tret = serializer.serialize(list, buffer);\n+\t\tif (!ret) {\n+\t\t\tcerr << \"List serialization without info map should have failed\"\n+\t\t\t     << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (buffer.overflow() || buffer.offset()) {\n+\t\t\tcerr << \"Failed list serialization modified the buffer\"\n+\t\t\t     << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\t/* Serialize the control info map. */\n+\t\tsize = serializer.binarySize(infoMap);\n+\t\tinfoData.resize(size);\n+\t\tbuffer = ByteStreamBuffer(infoData.data(), infoData.size());\n+\n+\t\tret = serializer.serialize(infoMap, buffer);\n+\t\tif (ret < 0) {\n+\t\t\tcerr << \"Failed to serialize ControlInfoMap\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (buffer.overflow()) {\n+\t\t\tcerr << \"Overflow when serializing ControlInfoMap\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\t/* Serialize the control list, this should now succeed. */\n+\t\tsize = serializer.binarySize(list);\n+\t\tlistData.resize(size);\n+\t\tbuffer = ByteStreamBuffer(listData.data(), listData.size());\n+\n+\t\tret = serializer.serialize(list, buffer);\n+\t\tif (ret) {\n+\t\t\tcerr << \"Failed to serialize ControlList\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (buffer.overflow()) {\n+\t\t\tcerr << \"Overflow when serializing ControlList\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\t/*\n+\t\t * Deserialize the control list, this should fail as the control\n+\t\t * info map hasn't been deserialized.\n+\t\t */\n+\t\tbuffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()),\n+\t\t\t\t\t  listData.size());\n+\n+\t\tControlList newList = deserializer.deserialize<ControlList>(buffer);\n+\t\tif (!newList.empty()) {\n+\t\t\tcerr << \"List deserialization without info map should have failed\"\n+\t\t\t     << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (buffer.overflow()) {\n+\t\t\tcerr << \"Failed list deserialization modified the buffer\"\n+\t\t\t     << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\t/* Deserialize the control info map and verify the contents. */\n+\t\tbuffer = ByteStreamBuffer(const_cast<const uint8_t *>(infoData.data()),\n+\t\t\t\t\t  infoData.size());\n+\n+\t\tControlInfoMap newInfoMap = deserializer.deserialize<ControlInfoMap>(buffer);\n+\t\tif (newInfoMap.empty()) {\n+\t\t\tcerr << \"Failed to deserialize ControlInfoMap\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (buffer.overflow()) {\n+\t\t\tcerr << \"Overflow when deserializing ControlInfoMap\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (!equals(infoMap, newInfoMap)) {\n+\t\t\tcerr << \"Deserialized map doesn't match original\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\t/* Deserialize the control list and verify the contents. */\n+\t\tbuffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()),\n+\t\t\t\t\t  listData.size());\n+\n+\t\tnewList = deserializer.deserialize<ControlList>(buffer);\n+\t\tif (newList.empty()) {\n+\t\t\tcerr << \"Failed to deserialize ControlList\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (buffer.overflow()) {\n+\t\t\tcerr << \"Overflow when deserializing ControlList\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\tif (!equals(list, newList)) {\n+\t\t\tcerr << \"Deserialized list doesn't match original\" << endl;\n+\t\t\treturn TestFail;\n+\t\t}\n+\n+\t\treturn TestPass;\n+\t}\n+};\n+\n+TEST_REGISTER(ControlSerializationTest)\ndiff --git a/test/serialization/meson.build b/test/serialization/meson.build\nnew file mode 100644\nindex 000000000000..d78d92e61887\n--- /dev/null\n+++ b/test/serialization/meson.build\n@@ -0,0 +1,11 @@\n+serialization_tests = [\n+    [ 'control_serialization',    'control_serialization.cpp' ],\n+]\n+\n+foreach t : serialization_tests\n+    exe = executable(t[0], [t[1], 'serialization_test.cpp'],\n+                     dependencies : libcamera_dep,\n+                     link_with : test_libraries,\n+                     include_directories : test_includes_internal)\n+    test(t[0], exe, suite : 'serialization', is_parallel : true)\n+endforeach\ndiff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp\nnew file mode 100644\nindex 000000000000..68e0512a04ca\n--- /dev/null\n+++ b/test/serialization/serialization_test.cpp\n@@ -0,0 +1,89 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * serialization_test.cpp - Base class for serialization tests\n+ */\n+\n+#include \"serialization_test.h\"\n+\n+#include <algorithm>\n+#include <iostream>\n+#include <map>\n+\n+#include <libcamera/camera.h>\n+#include <libcamera/camera_manager.h>\n+#include <libcamera/controls.h>\n+\n+#include \"test.h\"\n+\n+using namespace std;\n+using namespace libcamera;\n+\n+bool SerializationTest::equals(const ControlInfoMap &lhs, const ControlInfoMap &rhs)\n+{\n+\tstd::map<unsigned int, ControlRange> rlhs;\n+\tstd::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()),\n+\t\t\t[](const ControlInfoMap::value_type &v)\n+\t\t\t\t-> decltype(rlhs)::value_type\n+\t\t\t{\n+\t\t\t\treturn { v.first->id(), v.second };\n+\t\t\t});\n+\n+\tstd::map<unsigned int, ControlRange> rrhs;\n+\tstd::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()),\n+\t\t\t[](const ControlInfoMap::value_type &v)\n+\t\t\t\t-> decltype(rrhs)::value_type\n+\t\t\t{\n+\t\t\t\treturn { v.first->id(), v.second };\n+\t\t\t});\n+\n+\tif (rlhs == rrhs)\n+\t\treturn true;\n+\n+\tcerr << \"lhs:\" << endl;\n+\tfor (const auto &value : rlhs)\n+\t\tcerr << \"- \" << value.first << \": \"\n+\t\t     << value.second.toString() << endl;\n+\n+\tcerr << \"rhs:\" << endl;\n+\tfor (const auto &value : rrhs)\n+\t\tcerr << \"- \" << value.first << \": \"\n+\t\t     << value.second.toString() << endl;\n+\n+\treturn false;\n+}\n+\n+bool SerializationTest::equals(const ControlList &lhs, const ControlList &rhs)\n+{\n+\tstd::map<unsigned int, ControlValue> rlhs;\n+\tstd::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()),\n+\t\t\t[](const std::pair<unsigned int, ControlValue> &v)\n+\t\t\t\t-> decltype(rlhs)::value_type\n+\t\t\t{\n+\t\t\t\treturn { v.first, v.second };\n+\t\t\t});\n+\n+\tstd::map<unsigned int, ControlValue> rrhs;\n+\tstd::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()),\n+\t\t\t[](const std::pair<unsigned int, ControlValue> &v)\n+\t\t\t\t-> decltype(rrhs)::value_type\n+\t\t\t{\n+\t\t\t\treturn { v.first, v.second };\n+\t\t\t});\n+\n+\tif (rlhs == rrhs)\n+\t\treturn true;\n+\n+\tcerr << \"lhs:\" << endl;\n+\tfor (const auto &value : rlhs)\n+\t\tcerr << \"- \" << value.first << \": \"\n+\t\t     << value.second.toString() << endl;\n+\n+\tcerr << \"rhs:\" << endl;\n+\tfor (const auto &value : rrhs)\n+\t\tcerr << \"- \" << value.first << \": \"\n+\t\t     << value.second.toString() << endl;\n+\n+\treturn false;\n+}\ndiff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h\nnew file mode 100644\nindex 000000000000..fe77221ef5d0\n--- /dev/null\n+++ b/test/serialization/serialization_test.h\n@@ -0,0 +1,33 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * serialization_test.h - Base class for serialization tests\n+ */\n+#ifndef __LIBCAMERA_SERIALIZATION_TEST_H__\n+#define __LIBCAMERA_SERIALIZATION_TEST_H__\n+\n+#include <libcamera/camera.h>\n+#include <libcamera/camera_manager.h>\n+#include <libcamera/controls.h>\n+\n+#include \"camera_test.h\"\n+#include \"test.h\"\n+\n+using namespace libcamera;\n+\n+class SerializationTest : public CameraTest, public Test\n+{\n+public:\n+\tSerializationTest()\n+\t\t: CameraTest(\"VIMC Sensor B\")\n+\t{\n+\t}\n+\n+\tstatic bool equals(const ControlInfoMap &lhs,\n+\t\t\t   const ControlInfoMap &rhs);\n+\tstatic bool equals(const ControlList &lhs,\n+\t\t\t   const ControlList &rhs);\n+};\n+\n+#endif /* __LIBCAMERA_SERIALIZATION_TEST_H__ */\n","prefixes":["libcamera-devel","v2","17/24"]}