diff options
author | Jacopo Mondi <jacopo@jmondi.org> | 2019-10-22 01:58:15 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2019-11-20 21:47:54 +0200 |
commit | c0b437fd6cf7ca2e91eb749a25539f217722c66e (patch) | |
tree | b1172fd8b79b329a0df2882053a2fa9ef39fbbba | |
parent | 2c5f0ad23aa40d7410b28e01405c730e75c6cf83 (diff) |
test: Add control serialization test
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>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
-rw-r--r-- | test/meson.build | 1 | ||||
-rw-r--r-- | test/serialization/control_serialization.cpp | 166 | ||||
-rw-r--r-- | test/serialization/meson.build | 11 | ||||
-rw-r--r-- | test/serialization/serialization_test.cpp | 89 | ||||
-rw-r--r-- | test/serialization/serialization_test.h | 33 |
5 files changed, 300 insertions, 0 deletions
diff --git a/test/meson.build b/test/meson.build index adb5b29e..1bb2161d 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 00000000..2989b527 --- /dev/null +++ b/test/serialization/control_serialization.cpp @@ -0,0 +1,166 @@ +/* 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 init() override + { + return status_; + } + + 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 00000000..d78d92e6 --- /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 00000000..68e0512a --- /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 00000000..fe77221e --- /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__ */ |