From patchwork Tue Sep 24 17:24:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2011 Return-Path: Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2EB6662378 for ; Tue, 24 Sep 2019 19:23:36 +0200 (CEST) X-Originating-IP: 213.45.248.89 Received: from uno.homenet.telecomitalia.it (host89-248-dynamic.45-213-r.retail.telecomitalia.it [213.45.248.89]) (Authenticated sender: jacopo@jmondi.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 77B0D60006 for ; Tue, 24 Sep 2019 17:23:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 24 Sep 2019 19:24:54 +0200 Message-Id: <20190924172503.30864-13-jacopo@jmondi.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190924172503.30864-1-jacopo@jmondi.org> References: <20190924172503.30864-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 12/21] test: serialization: Add control serialization test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Sep 2019 17:23:36 -0000 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 --- 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 + +#include +#include +#include + +#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 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 + +#include +#include +#include + +#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(blob)); + uint32_t type = *(reinterpret_cast(Serializer::VALUE_BLOB_TYPE(blob))); + uint32_t size = *(reinterpret_cast(Serializer::VALUE_BLOB_SIZE(blob))); + uint32_t value = *(reinterpret_cast(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 +#include +#include + +#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 enumerator_; + std::shared_ptr media_; + std::shared_ptr camera_; + V4L2Subdevice *sensor_; + unsigned int numCtrls_; + CameraManager *cm_; +}; + +#endif /* __LIBCAMERA_SERIALIZATION_TEST_H__ */