[libcamera-devel] [PATCH 12/21] test: serialization: Add control serialization test
Jacopo Mondi
jacopo at jmondi.org
Tue Sep 24 19:24:54 CEST 2019
Test the serialization procedure of a ControlList by manually
unwrapping a serialized data blob containing controls supported by
the VIMC camera and verify its content.
Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
test/meson.build | 1 +
test/serialization/control_list.cpp | 101 ++++++++++++
test/serialization/meson.build | 11 ++
test/serialization/serialization_test.cpp | 189 ++++++++++++++++++++++
test/serialization/serialization_test.h | 65 ++++++++
5 files changed, 367 insertions(+)
create mode 100644 test/serialization/control_list.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 19e3031244a3..6d43273ca112 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_list.cpp b/test/serialization/control_list.cpp
new file mode 100644
index 000000000000..2cefec0cdc00
--- /dev/null
+++ b/test/serialization/control_list.cpp
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * control_list.cpp - Serialize and de-serialize a list of controls
+ */
+
+#include <iostream>
+
+#include <libcamera/camera.h>
+#include <libcamera/camera_manager.h>
+#include <libcamera/controls.h>
+
+#include "serialization_test.h"
+#include "serializer.h"
+#include "test.h"
+
+using namespace std;
+using namespace libcamera;
+
+class ControlListSerializeTest : public SerializationTest
+{
+private:
+ void initializeValidationMatrix()
+ {
+ valueValidationMatrix[0][0] = Saturation;
+ valueValidationMatrix[0][1] = DataTypeInteger;
+ valueValidationMatrix[0][2] = 8;
+ valueValidationMatrix[0][3] = 50;
+ valueValidationMatrix[0][4] = false;
+ valueValidationMatrix[1][0] = Contrast;
+ valueValidationMatrix[1][1] = DataTypeInteger;
+ valueValidationMatrix[1][2] = 8;
+ valueValidationMatrix[1][3] = 128;
+ valueValidationMatrix[1][4] = false;
+ valueValidationMatrix[2][0] = Brightness;
+ valueValidationMatrix[2][1] = DataTypeInteger;
+ valueValidationMatrix[2][2] = 8;
+ valueValidationMatrix[2][3] = 255;
+ valueValidationMatrix[2][4] = false;
+
+ numCtrls_ = 3;
+ }
+
+ int init()
+ {
+ return SerializationTest::init();
+ }
+
+ int run()
+ {
+ ControlList list(camera_->controls());
+
+ /*
+ * Set a 3 controls and manually unroll the serialized
+ * buffer to verify its content.
+ *
+ * \todo Test less trivial control types once we have them.
+ */
+ list[Brightness] = 255;
+ list[Contrast] = 128;
+ list[Saturation] = 50;
+
+ initializeValidationMatrix();
+
+ /* Serialize and verify the produced blob size. */
+ std::unique_ptr<DataBlob> blob = list.serialize();
+ if (!blob) {
+ cerr << "Failed to serialize the control list" << endl;
+ return TestFail;
+ }
+
+ int ret = validateValueBlobSize(blob.get());
+ if (ret)
+ return ret;
+
+ /* Validate each serialized data value. */
+ uint8_t *b = blob->data();
+ for (unsigned int i = 0; i < numCtrls_; ++i) {
+ if (!validateValueBlob(b))
+ return TestFail;
+
+ b += VALUE_BLOB_SIZE;
+ }
+
+ /* De-serialize a control list and re-validate it. */
+ ControlList newList(camera_->controls());
+ newList.deserialize(blob->data(), blob->size());
+ for (auto it : newList) {
+ const ControlInfo *info = it.first;
+ ControlValue &control = it.second;
+
+ if (!validateDataValue(info->id(), control))
+ return TestFail;
+ }
+
+ return TestPass;
+ }
+};
+
+TEST_REGISTER(ControlListSerializeTest)
diff --git a/test/serialization/meson.build b/test/serialization/meson.build
new file mode 100644
index 000000000000..511f05cbbd1f
--- /dev/null
+++ b/test/serialization/meson.build
@@ -0,0 +1,11 @@
+serialization_tests = [
+ [ 'control_list', 'control_list.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..8db70bb1de02
--- /dev/null
+++ b/test/serialization/serialization_test.cpp
@@ -0,0 +1,189 @@
+/* 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 <iostream>
+
+#include <libcamera/camera.h>
+#include <libcamera/camera_manager.h>
+#include <libcamera/controls.h>
+
+#include "test.h"
+#include "serializer.h"
+
+using namespace std;
+using namespace libcamera;
+
+SerializationTest::SerializationTest()
+ : sensor_(nullptr), numCtrls_(0), cm_(nullptr)
+{
+}
+
+int SerializationTest::init()
+{
+ cm_ = new CameraManager();
+
+ if (cm_->start()) {
+ cerr << "Failed to start camera manager" << endl;
+ return TestFail;
+ }
+
+ camera_ = cm_->get("VIMC Sensor B");
+ if (!camera_) {
+ cerr << "Can not find VIMC camera" << endl;
+ return TestSkip;
+ }
+
+ return TestPass;
+}
+
+void SerializationTest::cleanup()
+{
+ delete sensor_;
+
+ if (camera_) {
+ camera_->release();
+ camera_.reset();
+ }
+
+ cm_->stop();
+ delete cm_;
+}
+
+int SerializationTest::initSubdevice()
+{
+ enumerator_ = DeviceEnumerator::create();
+ if (!enumerator_) {
+ cerr << "Failed to create device enumerator" << endl;
+ return TestFail;
+ }
+
+ if (enumerator_->enumerate()) {
+ cerr << "Failed to enumerate media devices" << endl;
+ return TestFail;
+ }
+
+ DeviceMatch dm("vimc");
+ media_ = enumerator_->search(dm);
+ if (!media_) {
+ cerr << "Unable to find \'vimc\' media device node" << endl;
+ return TestSkip;
+ }
+
+ sensor_ = V4L2Subdevice::fromEntityName(media_.get(), "Sensor B");
+ if (sensor_->open()) {
+ cerr << "Unable to open video subdevice \"Sensor B\""
+ << endl;
+ return TestFail;
+ }
+
+ return TestPass;
+}
+
+int SerializationTest::validateValueBlobSize(DataBlob *blob)
+{
+ size_t blobSize = blob->size();
+ if (blobSize % Serializer::BLOB_ALIGN_BYTES) {
+ cerr << "Serialized control list has incorrect alignement"
+ << endl;
+ return TestFail;
+ }
+
+ size_t expectedSize = VALUE_BLOB_SIZE * numCtrls_;
+ if (blobSize != expectedSize) {
+ cerr << "Serialized control list has incorrect size: "
+ << " expected size " << expectedSize
+ << " got " << blobSize << endl;
+ return TestFail;
+ }
+
+ return TestPass;
+}
+
+bool SerializationTest::validateValueBlob(uint8_t *blob)
+{
+ uint32_t id = *(reinterpret_cast<uint32_t *>(blob));
+ uint32_t type = *(reinterpret_cast<uint32_t *>(Serializer::VALUE_BLOB_TYPE(blob)));
+ uint32_t size = *(reinterpret_cast<uint32_t *>(Serializer::VALUE_BLOB_SIZE(blob)));
+ uint32_t value = *(reinterpret_cast<uint32_t*>(Serializer::VALUE_BLOB_DATA(blob)));
+ bool found = false;
+
+ cout << "Testing serialized control: " << id << " - "
+ << type << " - " << size << " - " << value << endl;
+
+ for (unsigned int i = 0; i < numCtrls_; ++i) {
+ if (valueValidationMatrix[i][VALUE_CTRL_ID] != id)
+ continue;
+
+ found = true;
+
+ unsigned int *entry = valueValidationMatrix[i];
+ if (entry[VALUE_CTRL_FLAG]) {
+ cerr << "The control with id " << id
+ << " has been serialized twice" << endl;
+ return false;
+ }
+ entry[VALUE_CTRL_FLAG] = true;
+
+ if (entry[VALUE_CTRL_TYPE] != type ||
+ entry[VALUE_CTRL_SIZE] != size ||
+ entry[VALUE_CTRL_VALUE] != value) {
+ cerr << "The control with id " << id
+ << " has been wrongly serialized" << endl;
+ return false;
+ }
+ }
+
+ if (!found) {
+ cerr << "Non-existing control with id " << id << endl;
+ return false;
+ }
+
+ cout << "Serialization of control: " << id << " = Success."
+ << endl;
+
+ return true;
+}
+
+bool SerializationTest::validateDataValue(unsigned int id, const DataValue &dataValue)
+{
+ uint32_t value = dataValue.getInt();
+ DataType type = dataValue.type();
+ size_t dataSize = DataSize[type];
+ size_t size = dataValue.size();
+ bool found = false;
+
+ cout << "Testing de-serialized control: " << id << " - "
+ << type << " - " << size << " - " << value << endl;
+
+ for (unsigned int i = 0; i < numCtrls_; ++i) {
+ if (valueValidationMatrix[i][VALUE_CTRL_ID] != id)
+ continue;
+
+ found = true;
+
+ unsigned int *entry = valueValidationMatrix[i];
+ if (entry[VALUE_CTRL_TYPE] != dataValue.type() ||
+ dataSize != dataValue.size() ||
+ entry[VALUE_CTRL_VALUE] != value) {
+ cerr << "The control with id " << id
+ << " has been wrongly de-serialized" << endl;
+ return false;
+ }
+ }
+
+ if (!found) {
+ cerr << "Non-existing control with id " << id << endl;
+ return false;
+ }
+
+ cout << "De-serialization of control: " << id << " = Success."
+ << endl;
+
+ return true;
+}
diff --git a/test/serialization/serialization_test.h b/test/serialization/serialization_test.h
new file mode 100644
index 000000000000..87dc5a84a505
--- /dev/null
+++ b/test/serialization/serialization_test.h
@@ -0,0 +1,65 @@
+/* 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 "device_enumerator.h"
+#include "media_device.h"
+#include "serializer.h"
+#include "test.h"
+#include "v4l2_subdevice.h"
+
+using namespace libcamera;
+
+class SerializationTest : public Test
+{
+public:
+ SerializationTest();
+
+protected:
+ static constexpr unsigned int CTRL_MAX = 10;
+
+ /* Value validation matrix */
+ unsigned int valueValidationMatrix[3][5];
+
+ /* Indices on the validation matrix */
+ static constexpr unsigned int VALUE_CTRL_ID = 0;
+ static constexpr unsigned int VALUE_CTRL_TYPE = 1;
+ static constexpr unsigned int VALUE_CTRL_SIZE = 2;
+ static constexpr unsigned int VALUE_CTRL_VALUE = 3;
+ static constexpr unsigned int VALUE_CTRL_FLAG = 4;
+
+ /*
+ * Serialized values sizes.
+ * \todo Assume a serialized value is 24 bytes as all control
+ * values are simple integers.
+ */
+ static constexpr unsigned int VALUE_BLOB_DATA_SIZE = 8;
+ static constexpr unsigned int VALUE_BLOB_SIZE = 24;
+
+ int init();
+ void cleanup();
+
+ int initSubdevice();
+
+ int validateValueBlobSize(DataBlob *blob);
+ bool validateValueBlob(uint8_t *dataBlob);
+ bool validateDataValue(unsigned int id, const DataValue &dataValue);
+
+ std::unique_ptr<DeviceEnumerator> enumerator_;
+ std::shared_ptr<MediaDevice> media_;
+ std::shared_ptr<Camera> camera_;
+ V4L2Subdevice *sensor_;
+ unsigned int numCtrls_;
+ CameraManager *cm_;
+};
+
+#endif /* __LIBCAMERA_SERIALIZATION_TEST_H__ */
--
2.23.0
More information about the libcamera-devel
mailing list