Message ID | 20191108205409.18845-18-laurent.pinchart@ideasonboard.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Laurent, On Fri, Nov 08, 2019 at 10:54:02PM +0200, Laurent Pinchart wrote: > From: Jacopo Mondi <jacopo@jmondi.org> > > Add a test that exercises the ControlSerializer to serialize and > deserialize ControlInfoMap and ControlList. > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > test/meson.build | 1 + > test/serialization/control_serialization.cpp | 161 +++++++++++++++++++ > test/serialization/meson.build | 11 ++ > test/serialization/serialization_test.cpp | 89 ++++++++++ > test/serialization/serialization_test.h | 33 ++++ > 5 files changed, 295 insertions(+) > create mode 100644 test/serialization/control_serialization.cpp > create mode 100644 test/serialization/meson.build > create mode 100644 test/serialization/serialization_test.cpp > create mode 100644 test/serialization/serialization_test.h > > diff --git a/test/meson.build b/test/meson.build > index adb5b29e69f3..1bb2161dc05a 100644 > --- a/test/meson.build > +++ b/test/meson.build > @@ -8,6 +8,7 @@ subdir('log') > subdir('media_device') > subdir('pipeline') > subdir('process') > +subdir('serialization') > subdir('stream') > subdir('v4l2_subdevice') > subdir('v4l2_videodevice') > diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp > new file mode 100644 > index 000000000000..adfb498b5bd2 > --- /dev/null > +++ b/test/serialization/control_serialization.cpp > @@ -0,0 +1,161 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2019, Google Inc. > + * > + * control_serialization.cpp - Serialize and deserialize controls > + */ > + > +#include <iostream> > + > +#include <libcamera/camera.h> > +#include <libcamera/control_ids.h> > +#include <libcamera/controls.h> > + > +#include "byte_stream_buffer.h" > +#include "control_serializer.h" > +#include "serialization_test.h" > +#include "test.h" > + > +using namespace std; > +using namespace libcamera; > + > +class ControlSerializationTest : public SerializationTest > +{ > +protected: missing init() > + int run() override > + { > + ControlSerializer serializer; > + ControlSerializer deserializer; > + > + std::vector<uint8_t> infoData; > + std::vector<uint8_t> listData; > + > + size_t size; > + int ret; > + > + /* Create a control list with three controls. */ > + const ControlInfoMap &infoMap = camera_->controls(); > + ControlList list(infoMap); > + > + list.set(controls::Brightness, 255); > + list.set(controls::Contrast, 128); > + list.set(controls::Saturation, 50); > + > + /* > + * Serialize the control list, this should fail as the control > + * info map hasn't been serialized. > + */ > + size = serializer.binarySize(list); > + listData.resize(size); > + ByteStreamBuffer buffer(listData.data(), listData.size()); > + > + ret = serializer.serialize(list, buffer); > + if (!ret) { > + cerr << "List serialization without info map should have failed" > + << endl; > + return TestFail; > + } > + > + if (buffer.overflow() || buffer.offset()) { > + cerr << "Failed list serialization modified the buffer" > + << endl; > + return TestFail; > + } > + > + /* Serialize the control info map. */ > + size = serializer.binarySize(infoMap); > + infoData.resize(size); > + buffer = ByteStreamBuffer(infoData.data(), infoData.size()); > + > + ret = serializer.serialize(infoMap, buffer); > + if (ret < 0) { > + cerr << "Failed to serialize ControlInfoMap" << endl; > + return TestFail; > + } > + > + if (buffer.overflow()) { > + cerr << "Overflow when serializing ControlInfoMap" << endl; > + return TestFail; > + } > + > + /* Serialize the control list, this should now succeed. */ > + size = serializer.binarySize(list); > + listData.resize(size); > + buffer = ByteStreamBuffer(listData.data(), listData.size()); > + > + ret = serializer.serialize(list, buffer); > + if (ret) { > + cerr << "Failed to serialize ControlList" << endl; > + return TestFail; > + } > + > + if (buffer.overflow()) { > + cerr << "Overflow when serializing ControlList" << endl; > + return TestFail; > + } > + > + /* > + * Deserialize the control list, this should fail as the control > + * info map hasn't been deserialized. > + */ > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), > + listData.size()); > + > + ControlList newList = deserializer.deserialize<ControlList>(buffer); > + if (!newList.empty()) { > + cerr << "List deserialization without info map should have failed" > + << endl; > + return TestFail; > + } > + > + if (buffer.overflow()) { > + cerr << "Failed list deserialization modified the buffer" > + << endl; > + return TestFail; > + } > + > + /* Deserialize the control info map and verify the contents. */ > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(infoData.data()), > + infoData.size()); > + > + ControlInfoMap newInfoMap = deserializer.deserialize<ControlInfoMap>(buffer); > + if (newInfoMap.empty()) { > + cerr << "Failed to deserialize ControlInfoMap" << endl; > + return TestFail; > + } > + > + if (buffer.overflow()) { > + cerr << "Overflow when deserializing ControlInfoMap" << endl; > + return TestFail; > + } > + > + if (!equals(infoMap, newInfoMap)) { > + cerr << "Deserialized map doesn't match original" << endl; > + return TestFail; > + } > + > + /* Deserialize the control list and verify the contents. */ > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), > + listData.size()); > + > + newList = deserializer.deserialize<ControlList>(buffer); > + if (newList.empty()) { > + cerr << "Failed to deserialize ControlList" << endl; > + return TestFail; > + } > + > + if (buffer.overflow()) { > + cerr << "Overflow when deserializing ControlList" << endl; > + return TestFail; > + } > + > + if (!equals(list, newList)) { > + cerr << "Deserialized list doesn't match original" << endl; > + return TestFail; > + } > + > + return TestPass; > + } > +}; > + > +TEST_REGISTER(ControlSerializationTest) > diff --git a/test/serialization/meson.build b/test/serialization/meson.build > new file mode 100644 > index 000000000000..d78d92e61887 > --- /dev/null > +++ b/test/serialization/meson.build > @@ -0,0 +1,11 @@ > +serialization_tests = [ > + [ 'control_serialization', 'control_serialization.cpp' ], > +] > + > +foreach t : serialization_tests > + exe = executable(t[0], [t[1], 'serialization_test.cpp'], > + dependencies : libcamera_dep, > + link_with : test_libraries, > + include_directories : test_includes_internal) > + test(t[0], exe, suite : 'serialization', is_parallel : true) > +endforeach > diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp > new file mode 100644 > index 000000000000..68e0512a04ca > --- /dev/null > +++ b/test/serialization/serialization_test.cpp > @@ -0,0 +1,89 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2019, Google Inc. > + * > + * serialization_test.cpp - Base class for serialization tests > + */ > + > +#include "serialization_test.h" > + > +#include <algorithm> > +#include <iostream> > +#include <map> > + > +#include <libcamera/camera.h> > +#include <libcamera/camera_manager.h> > +#include <libcamera/controls.h> > + > +#include "test.h" > + > +using namespace std; > +using namespace libcamera; > + > +bool SerializationTest::equals(const ControlInfoMap &lhs, const ControlInfoMap &rhs) > +{ > + std::map<unsigned int, ControlRange> rlhs; > + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), > + [](const ControlInfoMap::value_type &v) > + -> decltype(rlhs)::value_type > + { > + return { v.first->id(), v.second }; > + }); > + > + std::map<unsigned int, ControlRange> rrhs; > + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), > + [](const ControlInfoMap::value_type &v) > + -> decltype(rrhs)::value_type > + { > + return { v.first->id(), v.second }; > + }); > + > + if (rlhs == rrhs) > + return true; > + > + cerr << "lhs:" << endl; > + for (const auto &value : rlhs) > + cerr << "- " << value.first << ": " > + << value.second.toString() << endl; > + > + cerr << "rhs:" << endl; > + for (const auto &value : rrhs) > + cerr << "- " << value.first << ": " > + << value.second.toString() << endl; > + > + return false; > +} > + > +bool SerializationTest::equals(const ControlList &lhs, const ControlList &rhs) > +{ > + std::map<unsigned int, ControlValue> rlhs; > + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), > + [](const std::pair<unsigned int, ControlValue> &v) > + -> decltype(rlhs)::value_type > + { > + return { v.first, v.second }; > + }); > + > + std::map<unsigned int, ControlValue> rrhs; > + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), > + [](const std::pair<unsigned int, ControlValue> &v) > + -> decltype(rrhs)::value_type > + { > + return { v.first, v.second }; > + }); > + > + if (rlhs == rrhs) > + return true; > + > + cerr << "lhs:" << endl; > + for (const auto &value : rlhs) > + cerr << "- " << value.first << ": " > + << value.second.toString() << endl; > + > + cerr << "rhs:" << endl; > + for (const auto &value : rrhs) > + cerr << "- " << value.first << ": " > + << value.second.toString() << endl; > + > + return false; > +} > diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h > new file mode 100644 > index 000000000000..fe77221ef5d0 > --- /dev/null > +++ b/test/serialization/serialization_test.h > @@ -0,0 +1,33 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2019, Google Inc. > + * > + * serialization_test.h - Base class for serialization tests > + */ > +#ifndef __LIBCAMERA_SERIALIZATION_TEST_H__ > +#define __LIBCAMERA_SERIALIZATION_TEST_H__ > + > +#include <libcamera/camera.h> > +#include <libcamera/camera_manager.h> > +#include <libcamera/controls.h> > + > +#include "camera_test.h" > +#include "test.h" > + > +using namespace libcamera; > + > +class SerializationTest : public CameraTest, public Test > +{ > +public: > + SerializationTest() > + : CameraTest("VIMC Sensor B") > + { > + } > + > + static bool equals(const ControlInfoMap &lhs, > + const ControlInfoMap &rhs); > + static bool equals(const ControlList &lhs, > + const ControlList &rhs); > +}; > + > +#endif /* __LIBCAMERA_SERIALIZATION_TEST_H__ */ > -- > Regards, > > Laurent Pinchart >
Hi Jacopo, On Fri, Nov 15, 2019 at 05:57:52PM +0100, Jacopo Mondi wrote: > On Fri, Nov 08, 2019 at 10:54:02PM +0200, Laurent Pinchart wrote: > > From: Jacopo Mondi <jacopo@jmondi.org> > > > > Add a test that exercises the ControlSerializer to serialize and > > deserialize ControlInfoMap and ControlList. > > > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > --- > > test/meson.build | 1 + > > test/serialization/control_serialization.cpp | 161 +++++++++++++++++++ > > test/serialization/meson.build | 11 ++ > > test/serialization/serialization_test.cpp | 89 ++++++++++ > > test/serialization/serialization_test.h | 33 ++++ > > 5 files changed, 295 insertions(+) > > create mode 100644 test/serialization/control_serialization.cpp > > create mode 100644 test/serialization/meson.build > > create mode 100644 test/serialization/serialization_test.cpp > > create mode 100644 test/serialization/serialization_test.h > > > > diff --git a/test/meson.build b/test/meson.build > > index adb5b29e69f3..1bb2161dc05a 100644 > > --- a/test/meson.build > > +++ b/test/meson.build > > @@ -8,6 +8,7 @@ subdir('log') > > subdir('media_device') > > subdir('pipeline') > > subdir('process') > > +subdir('serialization') > > subdir('stream') > > subdir('v4l2_subdevice') > > subdir('v4l2_videodevice') > > diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp > > new file mode 100644 > > index 000000000000..adfb498b5bd2 > > --- /dev/null > > +++ b/test/serialization/control_serialization.cpp > > @@ -0,0 +1,161 @@ > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > +/* > > + * Copyright (C) 2019, Google Inc. > > + * > > + * control_serialization.cpp - Serialize and deserialize controls > > + */ > > + > > +#include <iostream> > > + > > +#include <libcamera/camera.h> > > +#include <libcamera/control_ids.h> > > +#include <libcamera/controls.h> > > + > > +#include "byte_stream_buffer.h" > > +#include "control_serializer.h" > > +#include "serialization_test.h" > > +#include "test.h" > > + > > +using namespace std; > > +using namespace libcamera; > > + > > +class ControlSerializationTest : public SerializationTest > > +{ > > +protected: > > missing init() init() isn't mandatory. > > + int run() override > > + { > > + ControlSerializer serializer; > > + ControlSerializer deserializer; > > + > > + std::vector<uint8_t> infoData; > > + std::vector<uint8_t> listData; > > + > > + size_t size; > > + int ret; > > + > > + /* Create a control list with three controls. */ > > + const ControlInfoMap &infoMap = camera_->controls(); > > + ControlList list(infoMap); > > + > > + list.set(controls::Brightness, 255); > > + list.set(controls::Contrast, 128); > > + list.set(controls::Saturation, 50); > > + > > + /* > > + * Serialize the control list, this should fail as the control > > + * info map hasn't been serialized. > > + */ > > + size = serializer.binarySize(list); > > + listData.resize(size); > > + ByteStreamBuffer buffer(listData.data(), listData.size()); > > + > > + ret = serializer.serialize(list, buffer); > > + if (!ret) { > > + cerr << "List serialization without info map should have failed" > > + << endl; > > + return TestFail; > > + } > > + > > + if (buffer.overflow() || buffer.offset()) { > > + cerr << "Failed list serialization modified the buffer" > > + << endl; > > + return TestFail; > > + } > > + > > + /* Serialize the control info map. */ > > + size = serializer.binarySize(infoMap); > > + infoData.resize(size); > > + buffer = ByteStreamBuffer(infoData.data(), infoData.size()); > > + > > + ret = serializer.serialize(infoMap, buffer); > > + if (ret < 0) { > > + cerr << "Failed to serialize ControlInfoMap" << endl; > > + return TestFail; > > + } > > + > > + if (buffer.overflow()) { > > + cerr << "Overflow when serializing ControlInfoMap" << endl; > > + return TestFail; > > + } > > + > > + /* Serialize the control list, this should now succeed. */ > > + size = serializer.binarySize(list); > > + listData.resize(size); > > + buffer = ByteStreamBuffer(listData.data(), listData.size()); > > + > > + ret = serializer.serialize(list, buffer); > > + if (ret) { > > + cerr << "Failed to serialize ControlList" << endl; > > + return TestFail; > > + } > > + > > + if (buffer.overflow()) { > > + cerr << "Overflow when serializing ControlList" << endl; > > + return TestFail; > > + } > > + > > + /* > > + * Deserialize the control list, this should fail as the control > > + * info map hasn't been deserialized. > > + */ > > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), > > + listData.size()); > > + > > + ControlList newList = deserializer.deserialize<ControlList>(buffer); > > + if (!newList.empty()) { > > + cerr << "List deserialization without info map should have failed" > > + << endl; > > + return TestFail; > > + } > > + > > + if (buffer.overflow()) { > > + cerr << "Failed list deserialization modified the buffer" > > + << endl; > > + return TestFail; > > + } > > + > > + /* Deserialize the control info map and verify the contents. */ > > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(infoData.data()), > > + infoData.size()); > > + > > + ControlInfoMap newInfoMap = deserializer.deserialize<ControlInfoMap>(buffer); > > + if (newInfoMap.empty()) { > > + cerr << "Failed to deserialize ControlInfoMap" << endl; > > + return TestFail; > > + } > > + > > + if (buffer.overflow()) { > > + cerr << "Overflow when deserializing ControlInfoMap" << endl; > > + return TestFail; > > + } > > + > > + if (!equals(infoMap, newInfoMap)) { > > + cerr << "Deserialized map doesn't match original" << endl; > > + return TestFail; > > + } > > + > > + /* Deserialize the control list and verify the contents. */ > > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), > > + listData.size()); > > + > > + newList = deserializer.deserialize<ControlList>(buffer); > > + if (newList.empty()) { > > + cerr << "Failed to deserialize ControlList" << endl; > > + return TestFail; > > + } > > + > > + if (buffer.overflow()) { > > + cerr << "Overflow when deserializing ControlList" << endl; > > + return TestFail; > > + } > > + > > + if (!equals(list, newList)) { > > + cerr << "Deserialized list doesn't match original" << endl; > > + return TestFail; > > + } > > + > > + return TestPass; > > + } > > +}; > > + > > +TEST_REGISTER(ControlSerializationTest) > > diff --git a/test/serialization/meson.build b/test/serialization/meson.build > > new file mode 100644 > > index 000000000000..d78d92e61887 > > --- /dev/null > > +++ b/test/serialization/meson.build > > @@ -0,0 +1,11 @@ > > +serialization_tests = [ > > + [ 'control_serialization', 'control_serialization.cpp' ], > > +] > > + > > +foreach t : serialization_tests > > + exe = executable(t[0], [t[1], 'serialization_test.cpp'], > > + dependencies : libcamera_dep, > > + link_with : test_libraries, > > + include_directories : test_includes_internal) > > + test(t[0], exe, suite : 'serialization', is_parallel : true) > > +endforeach > > diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp > > new file mode 100644 > > index 000000000000..68e0512a04ca > > --- /dev/null > > +++ b/test/serialization/serialization_test.cpp > > @@ -0,0 +1,89 @@ > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > +/* > > + * Copyright (C) 2019, Google Inc. > > + * > > + * serialization_test.cpp - Base class for serialization tests > > + */ > > + > > +#include "serialization_test.h" > > + > > +#include <algorithm> > > +#include <iostream> > > +#include <map> > > + > > +#include <libcamera/camera.h> > > +#include <libcamera/camera_manager.h> > > +#include <libcamera/controls.h> > > + > > +#include "test.h" > > + > > +using namespace std; > > +using namespace libcamera; > > + > > +bool SerializationTest::equals(const ControlInfoMap &lhs, const ControlInfoMap &rhs) > > +{ > > + std::map<unsigned int, ControlRange> rlhs; > > + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), > > + [](const ControlInfoMap::value_type &v) > > + -> decltype(rlhs)::value_type > > + { > > + return { v.first->id(), v.second }; > > + }); > > + > > + std::map<unsigned int, ControlRange> rrhs; > > + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), > > + [](const ControlInfoMap::value_type &v) > > + -> decltype(rrhs)::value_type > > + { > > + return { v.first->id(), v.second }; > > + }); > > + > > + if (rlhs == rrhs) > > + return true; > > + > > + cerr << "lhs:" << endl; > > + for (const auto &value : rlhs) > > + cerr << "- " << value.first << ": " > > + << value.second.toString() << endl; > > + > > + cerr << "rhs:" << endl; > > + for (const auto &value : rrhs) > > + cerr << "- " << value.first << ": " > > + << value.second.toString() << endl; > > + > > + return false; > > +} > > + > > +bool SerializationTest::equals(const ControlList &lhs, const ControlList &rhs) > > +{ > > + std::map<unsigned int, ControlValue> rlhs; > > + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), > > + [](const std::pair<unsigned int, ControlValue> &v) > > + -> decltype(rlhs)::value_type > > + { > > + return { v.first, v.second }; > > + }); > > + > > + std::map<unsigned int, ControlValue> rrhs; > > + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), > > + [](const std::pair<unsigned int, ControlValue> &v) > > + -> decltype(rrhs)::value_type > > + { > > + return { v.first, v.second }; > > + }); > > + > > + if (rlhs == rrhs) > > + return true; > > + > > + cerr << "lhs:" << endl; > > + for (const auto &value : rlhs) > > + cerr << "- " << value.first << ": " > > + << value.second.toString() << endl; > > + > > + cerr << "rhs:" << endl; > > + for (const auto &value : rrhs) > > + cerr << "- " << value.first << ": " > > + << value.second.toString() << endl; > > + > > + return false; > > +} > > diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h > > new file mode 100644 > > index 000000000000..fe77221ef5d0 > > --- /dev/null > > +++ b/test/serialization/serialization_test.h > > @@ -0,0 +1,33 @@ > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > +/* > > + * Copyright (C) 2019, Google Inc. > > + * > > + * serialization_test.h - Base class for serialization tests > > + */ > > +#ifndef __LIBCAMERA_SERIALIZATION_TEST_H__ > > +#define __LIBCAMERA_SERIALIZATION_TEST_H__ > > + > > +#include <libcamera/camera.h> > > +#include <libcamera/camera_manager.h> > > +#include <libcamera/controls.h> > > + > > +#include "camera_test.h" > > +#include "test.h" > > + > > +using namespace libcamera; > > + > > +class SerializationTest : public CameraTest, public Test > > +{ > > +public: > > + SerializationTest() > > + : CameraTest("VIMC Sensor B") > > + { > > + } > > + > > + static bool equals(const ControlInfoMap &lhs, > > + const ControlInfoMap &rhs); > > + static bool equals(const ControlList &lhs, > > + const ControlList &rhs); > > +}; > > + > > +#endif /* __LIBCAMERA_SERIALIZATION_TEST_H__ */
Hi Laurent, Thanks for your work. On 2019-11-18 03:19:14 +0200, Laurent Pinchart wrote: > Hi Jacopo, > > On Fri, Nov 15, 2019 at 05:57:52PM +0100, Jacopo Mondi wrote: > > On Fri, Nov 08, 2019 at 10:54:02PM +0200, Laurent Pinchart wrote: > > > From: Jacopo Mondi <jacopo@jmondi.org> > > > > > > Add a test that exercises the ControlSerializer to serialize and > > > deserialize ControlInfoMap and ControlList. > > > > > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > --- > > > test/meson.build | 1 + > > > test/serialization/control_serialization.cpp | 161 +++++++++++++++++++ > > > test/serialization/meson.build | 11 ++ > > > test/serialization/serialization_test.cpp | 89 ++++++++++ > > > test/serialization/serialization_test.h | 33 ++++ > > > 5 files changed, 295 insertions(+) > > > create mode 100644 test/serialization/control_serialization.cpp > > > create mode 100644 test/serialization/meson.build > > > create mode 100644 test/serialization/serialization_test.cpp > > > create mode 100644 test/serialization/serialization_test.h > > > > > > diff --git a/test/meson.build b/test/meson.build > > > index adb5b29e69f3..1bb2161dc05a 100644 > > > --- a/test/meson.build > > > +++ b/test/meson.build > > > @@ -8,6 +8,7 @@ subdir('log') > > > subdir('media_device') > > > subdir('pipeline') > > > subdir('process') > > > +subdir('serialization') > > > subdir('stream') > > > subdir('v4l2_subdevice') > > > subdir('v4l2_videodevice') > > > diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp > > > new file mode 100644 > > > index 000000000000..adfb498b5bd2 > > > --- /dev/null > > > +++ b/test/serialization/control_serialization.cpp > > > @@ -0,0 +1,161 @@ > > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > > +/* > > > + * Copyright (C) 2019, Google Inc. > > > + * > > > + * control_serialization.cpp - Serialize and deserialize controls > > > + */ > > > + > > > +#include <iostream> > > > + > > > +#include <libcamera/camera.h> > > > +#include <libcamera/control_ids.h> > > > +#include <libcamera/controls.h> > > > + > > > +#include "byte_stream_buffer.h" > > > +#include "control_serializer.h" > > > +#include "serialization_test.h" > > > +#include "test.h" > > > + > > > +using namespace std; > > > +using namespace libcamera; > > > + > > > +class ControlSerializationTest : public SerializationTest > > > +{ > > > +protected: > > > > missing init() > > init() isn't mandatory. No but it inherits form CameraTest so maybe it's a good idea to check that a camera is found? int init() override { return status_; } With this fixed, Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> > > > > + int run() override > > > + { > > > + ControlSerializer serializer; > > > + ControlSerializer deserializer; > > > + > > > + std::vector<uint8_t> infoData; > > > + std::vector<uint8_t> listData; > > > + > > > + size_t size; > > > + int ret; > > > + > > > + /* Create a control list with three controls. */ > > > + const ControlInfoMap &infoMap = camera_->controls(); > > > + ControlList list(infoMap); > > > + > > > + list.set(controls::Brightness, 255); > > > + list.set(controls::Contrast, 128); > > > + list.set(controls::Saturation, 50); > > > + > > > + /* > > > + * Serialize the control list, this should fail as the control > > > + * info map hasn't been serialized. > > > + */ > > > + size = serializer.binarySize(list); > > > + listData.resize(size); > > > + ByteStreamBuffer buffer(listData.data(), listData.size()); > > > + > > > + ret = serializer.serialize(list, buffer); > > > + if (!ret) { > > > + cerr << "List serialization without info map should have failed" > > > + << endl; > > > + return TestFail; > > > + } > > > + > > > + if (buffer.overflow() || buffer.offset()) { > > > + cerr << "Failed list serialization modified the buffer" > > > + << endl; > > > + return TestFail; > > > + } > > > + > > > + /* Serialize the control info map. */ > > > + size = serializer.binarySize(infoMap); > > > + infoData.resize(size); > > > + buffer = ByteStreamBuffer(infoData.data(), infoData.size()); > > > + > > > + ret = serializer.serialize(infoMap, buffer); > > > + if (ret < 0) { > > > + cerr << "Failed to serialize ControlInfoMap" << endl; > > > + return TestFail; > > > + } > > > + > > > + if (buffer.overflow()) { > > > + cerr << "Overflow when serializing ControlInfoMap" << endl; > > > + return TestFail; > > > + } > > > + > > > + /* Serialize the control list, this should now succeed. */ > > > + size = serializer.binarySize(list); > > > + listData.resize(size); > > > + buffer = ByteStreamBuffer(listData.data(), listData.size()); > > > + > > > + ret = serializer.serialize(list, buffer); > > > + if (ret) { > > > + cerr << "Failed to serialize ControlList" << endl; > > > + return TestFail; > > > + } > > > + > > > + if (buffer.overflow()) { > > > + cerr << "Overflow when serializing ControlList" << endl; > > > + return TestFail; > > > + } > > > + > > > + /* > > > + * Deserialize the control list, this should fail as the control > > > + * info map hasn't been deserialized. > > > + */ > > > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), > > > + listData.size()); > > > + > > > + ControlList newList = deserializer.deserialize<ControlList>(buffer); > > > + if (!newList.empty()) { > > > + cerr << "List deserialization without info map should have failed" > > > + << endl; > > > + return TestFail; > > > + } > > > + > > > + if (buffer.overflow()) { > > > + cerr << "Failed list deserialization modified the buffer" > > > + << endl; > > > + return TestFail; > > > + } > > > + > > > + /* Deserialize the control info map and verify the contents. */ > > > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(infoData.data()), > > > + infoData.size()); > > > + > > > + ControlInfoMap newInfoMap = deserializer.deserialize<ControlInfoMap>(buffer); > > > + if (newInfoMap.empty()) { > > > + cerr << "Failed to deserialize ControlInfoMap" << endl; > > > + return TestFail; > > > + } > > > + > > > + if (buffer.overflow()) { > > > + cerr << "Overflow when deserializing ControlInfoMap" << endl; > > > + return TestFail; > > > + } > > > + > > > + if (!equals(infoMap, newInfoMap)) { > > > + cerr << "Deserialized map doesn't match original" << endl; > > > + return TestFail; > > > + } > > > + > > > + /* Deserialize the control list and verify the contents. */ > > > + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), > > > + listData.size()); > > > + > > > + newList = deserializer.deserialize<ControlList>(buffer); > > > + if (newList.empty()) { > > > + cerr << "Failed to deserialize ControlList" << endl; > > > + return TestFail; > > > + } > > > + > > > + if (buffer.overflow()) { > > > + cerr << "Overflow when deserializing ControlList" << endl; > > > + return TestFail; > > > + } > > > + > > > + if (!equals(list, newList)) { > > > + cerr << "Deserialized list doesn't match original" << endl; > > > + return TestFail; > > > + } > > > + > > > + return TestPass; > > > + } > > > +}; > > > + > > > +TEST_REGISTER(ControlSerializationTest) > > > diff --git a/test/serialization/meson.build b/test/serialization/meson.build > > > new file mode 100644 > > > index 000000000000..d78d92e61887 > > > --- /dev/null > > > +++ b/test/serialization/meson.build > > > @@ -0,0 +1,11 @@ > > > +serialization_tests = [ > > > + [ 'control_serialization', 'control_serialization.cpp' ], > > > +] > > > + > > > +foreach t : serialization_tests > > > + exe = executable(t[0], [t[1], 'serialization_test.cpp'], > > > + dependencies : libcamera_dep, > > > + link_with : test_libraries, > > > + include_directories : test_includes_internal) > > > + test(t[0], exe, suite : 'serialization', is_parallel : true) > > > +endforeach > > > diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp > > > new file mode 100644 > > > index 000000000000..68e0512a04ca > > > --- /dev/null > > > +++ b/test/serialization/serialization_test.cpp > > > @@ -0,0 +1,89 @@ > > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > > +/* > > > + * Copyright (C) 2019, Google Inc. > > > + * > > > + * serialization_test.cpp - Base class for serialization tests > > > + */ > > > + > > > +#include "serialization_test.h" > > > + > > > +#include <algorithm> > > > +#include <iostream> > > > +#include <map> > > > + > > > +#include <libcamera/camera.h> > > > +#include <libcamera/camera_manager.h> > > > +#include <libcamera/controls.h> > > > + > > > +#include "test.h" > > > + > > > +using namespace std; > > > +using namespace libcamera; > > > + > > > +bool SerializationTest::equals(const ControlInfoMap &lhs, const ControlInfoMap &rhs) > > > +{ > > > + std::map<unsigned int, ControlRange> rlhs; > > > + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), > > > + [](const ControlInfoMap::value_type &v) > > > + -> decltype(rlhs)::value_type > > > + { > > > + return { v.first->id(), v.second }; > > > + }); > > > + > > > + std::map<unsigned int, ControlRange> rrhs; > > > + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), > > > + [](const ControlInfoMap::value_type &v) > > > + -> decltype(rrhs)::value_type > > > + { > > > + return { v.first->id(), v.second }; > > > + }); > > > + > > > + if (rlhs == rrhs) > > > + return true; > > > + > > > + cerr << "lhs:" << endl; > > > + for (const auto &value : rlhs) > > > + cerr << "- " << value.first << ": " > > > + << value.second.toString() << endl; > > > + > > > + cerr << "rhs:" << endl; > > > + for (const auto &value : rrhs) > > > + cerr << "- " << value.first << ": " > > > + << value.second.toString() << endl; > > > + > > > + return false; > > > +} > > > + > > > +bool SerializationTest::equals(const ControlList &lhs, const ControlList &rhs) > > > +{ > > > + std::map<unsigned int, ControlValue> rlhs; > > > + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), > > > + [](const std::pair<unsigned int, ControlValue> &v) > > > + -> decltype(rlhs)::value_type > > > + { > > > + return { v.first, v.second }; > > > + }); > > > + > > > + std::map<unsigned int, ControlValue> rrhs; > > > + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), > > > + [](const std::pair<unsigned int, ControlValue> &v) > > > + -> decltype(rrhs)::value_type > > > + { > > > + return { v.first, v.second }; > > > + }); > > > + > > > + if (rlhs == rrhs) > > > + return true; > > > + > > > + cerr << "lhs:" << endl; > > > + for (const auto &value : rlhs) > > > + cerr << "- " << value.first << ": " > > > + << value.second.toString() << endl; > > > + > > > + cerr << "rhs:" << endl; > > > + for (const auto &value : rrhs) > > > + cerr << "- " << value.first << ": " > > > + << value.second.toString() << endl; > > > + > > > + return false; > > > +} > > > diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h > > > new file mode 100644 > > > index 000000000000..fe77221ef5d0 > > > --- /dev/null > > > +++ b/test/serialization/serialization_test.h > > > @@ -0,0 +1,33 @@ > > > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > > > +/* > > > + * Copyright (C) 2019, Google Inc. > > > + * > > > + * serialization_test.h - Base class for serialization tests > > > + */ > > > +#ifndef __LIBCAMERA_SERIALIZATION_TEST_H__ > > > +#define __LIBCAMERA_SERIALIZATION_TEST_H__ > > > + > > > +#include <libcamera/camera.h> > > > +#include <libcamera/camera_manager.h> > > > +#include <libcamera/controls.h> > > > + > > > +#include "camera_test.h" > > > +#include "test.h" > > > + > > > +using namespace libcamera; > > > + > > > +class SerializationTest : public CameraTest, public Test > > > +{ > > > +public: > > > + SerializationTest() > > > + : CameraTest("VIMC Sensor B") > > > + { > > > + } > > > + > > > + static bool equals(const ControlInfoMap &lhs, > > > + const ControlInfoMap &rhs); > > > + static bool equals(const ControlList &lhs, > > > + const ControlList &rhs); > > > +}; > > > + > > > +#endif /* __LIBCAMERA_SERIALIZATION_TEST_H__ */ > > -- > Regards, > > Laurent Pinchart > _______________________________________________ > libcamera-devel mailing list > libcamera-devel@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel
diff --git a/test/meson.build b/test/meson.build index adb5b29e69f3..1bb2161dc05a 100644 --- a/test/meson.build +++ b/test/meson.build @@ -8,6 +8,7 @@ subdir('log') subdir('media_device') subdir('pipeline') subdir('process') +subdir('serialization') subdir('stream') subdir('v4l2_subdevice') subdir('v4l2_videodevice') diff --git a/test/serialization/control_serialization.cpp b/test/serialization/control_serialization.cpp new file mode 100644 index 000000000000..adfb498b5bd2 --- /dev/null +++ b/test/serialization/control_serialization.cpp @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * control_serialization.cpp - Serialize and deserialize controls + */ + +#include <iostream> + +#include <libcamera/camera.h> +#include <libcamera/control_ids.h> +#include <libcamera/controls.h> + +#include "byte_stream_buffer.h" +#include "control_serializer.h" +#include "serialization_test.h" +#include "test.h" + +using namespace std; +using namespace libcamera; + +class ControlSerializationTest : public SerializationTest +{ +protected: + int run() override + { + ControlSerializer serializer; + ControlSerializer deserializer; + + std::vector<uint8_t> infoData; + std::vector<uint8_t> listData; + + size_t size; + int ret; + + /* Create a control list with three controls. */ + const ControlInfoMap &infoMap = camera_->controls(); + ControlList list(infoMap); + + list.set(controls::Brightness, 255); + list.set(controls::Contrast, 128); + list.set(controls::Saturation, 50); + + /* + * Serialize the control list, this should fail as the control + * info map hasn't been serialized. + */ + size = serializer.binarySize(list); + listData.resize(size); + ByteStreamBuffer buffer(listData.data(), listData.size()); + + ret = serializer.serialize(list, buffer); + if (!ret) { + cerr << "List serialization without info map should have failed" + << endl; + return TestFail; + } + + if (buffer.overflow() || buffer.offset()) { + cerr << "Failed list serialization modified the buffer" + << endl; + return TestFail; + } + + /* Serialize the control info map. */ + size = serializer.binarySize(infoMap); + infoData.resize(size); + buffer = ByteStreamBuffer(infoData.data(), infoData.size()); + + ret = serializer.serialize(infoMap, buffer); + if (ret < 0) { + cerr << "Failed to serialize ControlInfoMap" << endl; + return TestFail; + } + + if (buffer.overflow()) { + cerr << "Overflow when serializing ControlInfoMap" << endl; + return TestFail; + } + + /* Serialize the control list, this should now succeed. */ + size = serializer.binarySize(list); + listData.resize(size); + buffer = ByteStreamBuffer(listData.data(), listData.size()); + + ret = serializer.serialize(list, buffer); + if (ret) { + cerr << "Failed to serialize ControlList" << endl; + return TestFail; + } + + if (buffer.overflow()) { + cerr << "Overflow when serializing ControlList" << endl; + return TestFail; + } + + /* + * Deserialize the control list, this should fail as the control + * info map hasn't been deserialized. + */ + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), + listData.size()); + + ControlList newList = deserializer.deserialize<ControlList>(buffer); + if (!newList.empty()) { + cerr << "List deserialization without info map should have failed" + << endl; + return TestFail; + } + + if (buffer.overflow()) { + cerr << "Failed list deserialization modified the buffer" + << endl; + return TestFail; + } + + /* Deserialize the control info map and verify the contents. */ + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(infoData.data()), + infoData.size()); + + ControlInfoMap newInfoMap = deserializer.deserialize<ControlInfoMap>(buffer); + if (newInfoMap.empty()) { + cerr << "Failed to deserialize ControlInfoMap" << endl; + return TestFail; + } + + if (buffer.overflow()) { + cerr << "Overflow when deserializing ControlInfoMap" << endl; + return TestFail; + } + + if (!equals(infoMap, newInfoMap)) { + cerr << "Deserialized map doesn't match original" << endl; + return TestFail; + } + + /* Deserialize the control list and verify the contents. */ + buffer = ByteStreamBuffer(const_cast<const uint8_t *>(listData.data()), + listData.size()); + + newList = deserializer.deserialize<ControlList>(buffer); + if (newList.empty()) { + cerr << "Failed to deserialize ControlList" << endl; + return TestFail; + } + + if (buffer.overflow()) { + cerr << "Overflow when deserializing ControlList" << endl; + return TestFail; + } + + if (!equals(list, newList)) { + cerr << "Deserialized list doesn't match original" << endl; + return TestFail; + } + + return TestPass; + } +}; + +TEST_REGISTER(ControlSerializationTest) diff --git a/test/serialization/meson.build b/test/serialization/meson.build new file mode 100644 index 000000000000..d78d92e61887 --- /dev/null +++ b/test/serialization/meson.build @@ -0,0 +1,11 @@ +serialization_tests = [ + [ 'control_serialization', 'control_serialization.cpp' ], +] + +foreach t : serialization_tests + exe = executable(t[0], [t[1], 'serialization_test.cpp'], + dependencies : libcamera_dep, + link_with : test_libraries, + include_directories : test_includes_internal) + test(t[0], exe, suite : 'serialization', is_parallel : true) +endforeach diff --git a/test/serialization/serialization_test.cpp b/test/serialization/serialization_test.cpp new file mode 100644 index 000000000000..68e0512a04ca --- /dev/null +++ b/test/serialization/serialization_test.cpp @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * serialization_test.cpp - Base class for serialization tests + */ + +#include "serialization_test.h" + +#include <algorithm> +#include <iostream> +#include <map> + +#include <libcamera/camera.h> +#include <libcamera/camera_manager.h> +#include <libcamera/controls.h> + +#include "test.h" + +using namespace std; +using namespace libcamera; + +bool SerializationTest::equals(const ControlInfoMap &lhs, const ControlInfoMap &rhs) +{ + std::map<unsigned int, ControlRange> rlhs; + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), + [](const ControlInfoMap::value_type &v) + -> decltype(rlhs)::value_type + { + return { v.first->id(), v.second }; + }); + + std::map<unsigned int, ControlRange> rrhs; + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), + [](const ControlInfoMap::value_type &v) + -> decltype(rrhs)::value_type + { + return { v.first->id(), v.second }; + }); + + if (rlhs == rrhs) + return true; + + cerr << "lhs:" << endl; + for (const auto &value : rlhs) + cerr << "- " << value.first << ": " + << value.second.toString() << endl; + + cerr << "rhs:" << endl; + for (const auto &value : rrhs) + cerr << "- " << value.first << ": " + << value.second.toString() << endl; + + return false; +} + +bool SerializationTest::equals(const ControlList &lhs, const ControlList &rhs) +{ + std::map<unsigned int, ControlValue> rlhs; + std::transform(lhs.begin(), lhs.end(), std::inserter(rlhs, rlhs.end()), + [](const std::pair<unsigned int, ControlValue> &v) + -> decltype(rlhs)::value_type + { + return { v.first, v.second }; + }); + + std::map<unsigned int, ControlValue> rrhs; + std::transform(rhs.begin(), rhs.end(), std::inserter(rrhs, rrhs.end()), + [](const std::pair<unsigned int, ControlValue> &v) + -> decltype(rrhs)::value_type + { + return { v.first, v.second }; + }); + + if (rlhs == rrhs) + return true; + + cerr << "lhs:" << endl; + for (const auto &value : rlhs) + cerr << "- " << value.first << ": " + << value.second.toString() << endl; + + cerr << "rhs:" << endl; + for (const auto &value : rrhs) + cerr << "- " << value.first << ": " + << value.second.toString() << endl; + + return false; +} diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h new file mode 100644 index 000000000000..fe77221ef5d0 --- /dev/null +++ b/test/serialization/serialization_test.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * serialization_test.h - Base class for serialization tests + */ +#ifndef __LIBCAMERA_SERIALIZATION_TEST_H__ +#define __LIBCAMERA_SERIALIZATION_TEST_H__ + +#include <libcamera/camera.h> +#include <libcamera/camera_manager.h> +#include <libcamera/controls.h> + +#include "camera_test.h" +#include "test.h" + +using namespace libcamera; + +class SerializationTest : public CameraTest, public Test +{ +public: + SerializationTest() + : CameraTest("VIMC Sensor B") + { + } + + static bool equals(const ControlInfoMap &lhs, + const ControlInfoMap &rhs); + static bool equals(const ControlList &lhs, + const ControlList &rhs); +}; + +#endif /* __LIBCAMERA_SERIALIZATION_TEST_H__ */