[{"id":3030,"web_url":"https://patchwork.libcamera.org/comment/3030/","msgid":"<20191115165752.wceyjaeocjx4mclb@uno.localdomain>","date":"2019-11-15T16:57:52","subject":"Re: [libcamera-devel] [PATCH v2 17/24] test: Add control\n\tserialization test","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Fri, Nov 08, 2019 at 10:54:02PM +0200, Laurent Pinchart wrote:\n> From: Jacopo Mondi <jacopo@jmondi.org>\n>\n> Add a test that exercises the ControlSerializer to serialize and\n> deserialize ControlInfoMap and ControlList.\n>\n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> Signed-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\n>\n> diff --git a/test/meson.build b/test/meson.build\n> index 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')\n> diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp\n> new file mode 100644\n> index 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\nmissing init()\n\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)\n> diff --git a/test/serialization/meson.build b/test/serialization/meson.build\n> new file mode 100644\n> index 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\n> diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp\n> new file mode 100644\n> index 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> +}\n> diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h\n> new file mode 100644\n> index 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> --\n> Regards,\n>\n> Laurent Pinchart\n>","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net\n\t[217.70.183.197])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6B77E6136F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 15 Nov 2019 17:55:51 +0100 (CET)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay5-d.mail.gandi.net (Postfix) with ESMTPSA id EA3521C000C;\n\tFri, 15 Nov 2019 16:55:50 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Fri, 15 Nov 2019 17:57:52 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20191115165752.wceyjaeocjx4mclb@uno.localdomain>","References":"<20191108205409.18845-1-laurent.pinchart@ideasonboard.com>\n\t<20191108205409.18845-18-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"wirg5mo5mnlplrez\"","Content-Disposition":"inline","In-Reply-To":"<20191108205409.18845-18-laurent.pinchart@ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v2 17/24] test: Add control\n\tserialization test","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, 15 Nov 2019 16:55:51 -0000"}},{"id":3045,"web_url":"https://patchwork.libcamera.org/comment/3045/","msgid":"<20191118011914.GQ4853@pendragon.ideasonboard.com>","date":"2019-11-18T01:19:14","subject":"Re: [libcamera-devel] [PATCH v2 17/24] test: Add control\n\tserialization test","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Fri, Nov 15, 2019 at 05:57:52PM +0100, Jacopo Mondi wrote:\n> On Fri, Nov 08, 2019 at 10:54:02PM +0200, Laurent Pinchart wrote:\n> > From: Jacopo Mondi <jacopo@jmondi.org>\n> >\n> > Add a test that exercises the ControlSerializer to serialize and\n> > deserialize ControlInfoMap and ControlList.\n> >\n> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > Signed-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\n> >\n> > diff --git a/test/meson.build b/test/meson.build\n> > index 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')\n> > diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp\n> > new file mode 100644\n> > index 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> \n> missing init()\n\ninit() isn't mandatory.\n\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)\n> > diff --git a/test/serialization/meson.build b/test/serialization/meson.build\n> > new file mode 100644\n> > index 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\n> > diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp\n> > new file mode 100644\n> > index 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> > +}\n> > diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h\n> > new file mode 100644\n> > index 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__ */","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id DB63960C33\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Nov 2019 02:19:18 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 61727540;\n\tMon, 18 Nov 2019 02:19:18 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1574039958;\n\tbh=JMMq5VsSSmDMqtkIABJAnpydwBjY09yWjS77vM/Sl2M=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=P5SC85EFzphAcSZVdsSdxyRrL7J/vrIbB+Ov3nJLswAGLJkW8JMGJq99mKRi9w8f6\n\twVLyW5dS7rV+cxIv0mz8yj7ztz7AzX08fXGwn047Z/Ev1FC66pXThdz8qDnMyYZ/bk\n\t+IOzV2OFZUxQt2v7kUWv7+Sdhz8C4H57epKkGCCY=","Date":"Mon, 18 Nov 2019 03:19:14 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20191118011914.GQ4853@pendragon.ideasonboard.com>","References":"<20191108205409.18845-1-laurent.pinchart@ideasonboard.com>\n\t<20191108205409.18845-18-laurent.pinchart@ideasonboard.com>\n\t<20191115165752.wceyjaeocjx4mclb@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20191115165752.wceyjaeocjx4mclb@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v2 17/24] test: Add control\n\tserialization test","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":"Mon, 18 Nov 2019 01:19:19 -0000"}},{"id":3081,"web_url":"https://patchwork.libcamera.org/comment/3081/","msgid":"<20191118214724.GL8072@bigcity.dyn.berto.se>","date":"2019-11-18T21:47:24","subject":"Re: [libcamera-devel] [PATCH v2 17/24] test: Add control\n\tserialization test","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Laurent,\n\nThanks for your work.\n\nOn 2019-11-18 03:19:14 +0200, Laurent Pinchart wrote:\n> Hi Jacopo,\n> \n> On Fri, Nov 15, 2019 at 05:57:52PM +0100, Jacopo Mondi wrote:\n> > On Fri, Nov 08, 2019 at 10:54:02PM +0200, Laurent Pinchart wrote:\n> > > From: Jacopo Mondi <jacopo@jmondi.org>\n> > >\n> > > Add a test that exercises the ControlSerializer to serialize and\n> > > deserialize ControlInfoMap and ControlList.\n> > >\n> > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > > Signed-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\n> > >\n> > > diff --git a/test/meson.build b/test/meson.build\n> > > index 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')\n> > > diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp\n> > > new file mode 100644\n> > > index 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> > \n> > missing init()\n> \n> init() isn't mandatory.\n\nNo but it inherits form CameraTest so maybe it's a good idea to check \nthat a camera is found?\n\n   int init() override\n   {\n       return status_;\n   }\n\nWith this fixed,\n\nReviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\n> \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)\n> > > diff --git a/test/serialization/meson.build b/test/serialization/meson.build\n> > > new file mode 100644\n> > > index 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\n> > > diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp\n> > > new file mode 100644\n> > > index 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> > > +}\n> > > diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h\n> > > new file mode 100644\n> > > index 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> \n> -- \n> Regards,\n> \n> Laurent Pinchart\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-lf1-x143.google.com (mail-lf1-x143.google.com\n\t[IPv6:2a00:1450:4864:20::143])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id DD74D60F1C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Nov 2019 22:47:26 +0100 (CET)","by mail-lf1-x143.google.com with SMTP id d6so15121500lfc.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Nov 2019 13:47:26 -0800 (PST)","from localhost (h-93-159.A463.priv.bahnhof.se. [46.59.93.159])\n\tby smtp.gmail.com with ESMTPSA id\n\tc12sm8459407ljk.77.2019.11.18.13.47.24\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 18 Nov 2019 13:47:24 -0800 (PST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to\n\t:user-agent; bh=I9IzjQ+hiM0EDZscDi7aysRaZdCfsCHQlk/2huIJciY=;\n\tb=QHwKcLlIaT5Tm0R8kVj0p4o3Ifn6wvgNcrF/O+xLgl2dJnYBVuiamA2GaubnaQ0aGP\n\tNUEc+6kkxQjx8FSS+G6N0L9fS+4Z0h2U+RbmTNMMpVtlcjxQsMDXjZiGvZdDioKFjbBQ\n\tvkkNx8JKS4yR3Je/U4g/il0CRLcYfh3aJGFv/suXoCFwa9DTxG42rOO/tqJyo2fRoATb\n\tCBalp+PEJFlc7yGd3tLHYMukmY3yIplYuTRttNsO4j7y2Do1OgfT/sy9L6MsXRkglIZI\n\tzu0gtKSnsN/dAq98JrqRJqWkt11PXWWln9uKXSVpqDPHqYn5psq/+NklxRdYOQbSAcBz\n\td70g==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to:user-agent;\n\tbh=I9IzjQ+hiM0EDZscDi7aysRaZdCfsCHQlk/2huIJciY=;\n\tb=PBGnBinawjYUP9pMqvIr97P7M1qd+UQcUa1CuXFOx1VM/dvt9AHiWYKChHGX08q+FV\n\tT+TZ+Pj2RB1uZNPTxgPETkWKUTJI6HNC+wIsR+GNT3SZWNvp3GcVzQy/88xpZVGMlR49\n\trFvkO5rZN/Idp2XeypBEi9nTTL+ygLJ1V/KfhSxaJ5hepVQhP35ulNtWeyLqzUn87LVQ\n\tey4a+hmGBaG5V0XNylr/boq3ei2wjQ25qBM2OIaq/n1K/qdQnyOaZlKLlIJt+NO9mfQK\n\tgS+zolgfzOq4Xmytlm61jbRnpKK9GVPoRVFP02k4Ex08855iFD4fxK8GAys6zhy6zKYk\n\tD9VA==","X-Gm-Message-State":"APjAAAXCgQMUVb7pOok/8Mtqkbg9yNllMWL2Dd25JbLDaekry1pE7AeW\n\tckoHwBqxSZfHUtfSS0oU4ueuKP+Mv/4=","X-Google-Smtp-Source":"APXvYqyukmaTTbuChrsFWfDkrBAjD3t3lp1EX1/GE7LRtgsC9xKrstibiOY13mF6FlUKJb/odgFZIA==","X-Received":"by 2002:a19:a410:: with SMTP id\n\tq16mr1135789lfc.184.1574113645986; \n\tMon, 18 Nov 2019 13:47:25 -0800 (PST)","Date":"Mon, 18 Nov 2019 22:47:24 +0100","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo@jmondi.org>, libcamera-devel@lists.libcamera.org","Message-ID":"<20191118214724.GL8072@bigcity.dyn.berto.se>","References":"<20191108205409.18845-1-laurent.pinchart@ideasonboard.com>\n\t<20191108205409.18845-18-laurent.pinchart@ideasonboard.com>\n\t<20191115165752.wceyjaeocjx4mclb@uno.localdomain>\n\t<20191118011914.GQ4853@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20191118011914.GQ4853@pendragon.ideasonboard.com>","User-Agent":"Mutt/1.12.1 (2019-06-15)","Subject":"Re: [libcamera-devel] [PATCH v2 17/24] test: Add control\n\tserialization test","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":"Mon, 18 Nov 2019 21:47:27 -0000"}}]