An attempt at getting image data back
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* Serialize and deserialize controls
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <libcamera/camera.h>
|
||||
#include <libcamera/control_ids.h>
|
||||
#include <libcamera/controls.h>
|
||||
|
||||
#include "libcamera/internal/byte_stream_buffer.h"
|
||||
#include "libcamera/internal/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::Role::Proxy);
|
||||
ControlSerializer deserializer(ControlSerializer::Role::Worker);
|
||||
|
||||
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, 0.5f);
|
||||
list.set(controls::Contrast, 1.2f);
|
||||
list.set(controls::Saturation, 0.2f);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* Make sure control limits looked up by id are not changed. */
|
||||
const ControlInfo &newLimits = newInfoMap.at(&controls::Brightness);
|
||||
const ControlInfo &initialLimits = infoMap.at(&controls::Brightness);
|
||||
if (newLimits.min() != initialLimits.min() ||
|
||||
newLimits.max() != initialLimits.max()) {
|
||||
cerr << "The brightness control limits have changed" << 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)
|
||||
@@ -0,0 +1,181 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2020, Google Inc.
|
||||
*
|
||||
* Test generated serializer
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "test_ipa_interface.h"
|
||||
#include "test_ipa_serializer.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libcamera;
|
||||
|
||||
class IPAGeneratedSerializerTest : public Test
|
||||
{
|
||||
protected:
|
||||
int init() override
|
||||
{
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
|
||||
#define TEST_FIELD_EQUALITY(struct1, struct2, field) \
|
||||
if (struct1.field != struct2.field) { \
|
||||
cerr << #field << " field incorrect: expected \"" \
|
||||
<< t.field << "\", got \"" << u.field << "\"" << endl;\
|
||||
return TestFail; \
|
||||
}
|
||||
|
||||
#define TEST_SCOPED_ENUM_EQUALITY(struct1, struct2, field) \
|
||||
if (struct1.field != struct2.field) { \
|
||||
cerr << #field << " field incorrect" << endl; \
|
||||
return TestFail; \
|
||||
}
|
||||
|
||||
|
||||
ipa::test::TestStruct t, u;
|
||||
|
||||
t.m = {
|
||||
{ "a", "z" },
|
||||
{ "b", "z" },
|
||||
{ "c", "z" },
|
||||
{ "d", "z" },
|
||||
{ "e", "z" },
|
||||
};
|
||||
|
||||
t.a = { "a", "b", "c", "d", "e" };
|
||||
|
||||
t.s1 = "hello world";
|
||||
t.s2 = "goodbye";
|
||||
t.s3 = "lorem ipsum";
|
||||
t.i = 58527;
|
||||
t.c = ipa::test::IPAOperationInit;
|
||||
t.e = ipa::test::ErrorFlags::Error1;
|
||||
|
||||
Flags<ipa::test::ErrorFlags> flags;
|
||||
flags |= ipa::test::ErrorFlags::Error1;
|
||||
flags |= ipa::test::ErrorFlags::Error2;
|
||||
t.f = flags;
|
||||
|
||||
std::vector<uint8_t> serialized;
|
||||
|
||||
std::tie(serialized, ignore) =
|
||||
IPADataSerializer<ipa::test::TestStruct>::serialize(t);
|
||||
|
||||
u = IPADataSerializer<ipa::test::TestStruct>::deserialize(serialized);
|
||||
|
||||
if (!equals(t.m, u.m))
|
||||
return TestFail;
|
||||
|
||||
if (!equals(t.a, u.a))
|
||||
return TestFail;
|
||||
|
||||
TEST_FIELD_EQUALITY(t, u, s1);
|
||||
TEST_FIELD_EQUALITY(t, u, s2);
|
||||
TEST_FIELD_EQUALITY(t, u, s3);
|
||||
TEST_FIELD_EQUALITY(t, u, i);
|
||||
TEST_FIELD_EQUALITY(t, u, c);
|
||||
|
||||
TEST_SCOPED_ENUM_EQUALITY(t, u, e);
|
||||
TEST_SCOPED_ENUM_EQUALITY(t, u, f);
|
||||
|
||||
/* Test vector of generated structs */
|
||||
std::vector<ipa::test::TestStruct> v = { t, u };
|
||||
std::vector<ipa::test::TestStruct> w;
|
||||
|
||||
std::tie(serialized, ignore) =
|
||||
IPADataSerializer<vector<ipa::test::TestStruct>>::serialize(v);
|
||||
|
||||
w = IPADataSerializer<vector<ipa::test::TestStruct>>::deserialize(serialized);
|
||||
|
||||
if (!equals(v[0].m, w[0].m) ||
|
||||
!equals(v[1].m, w[1].m))
|
||||
return TestFail;
|
||||
|
||||
if (!equals(v[0].a, w[0].a) ||
|
||||
!equals(v[1].a, w[1].a))
|
||||
return TestFail;
|
||||
|
||||
TEST_FIELD_EQUALITY(v[0], w[0], s1);
|
||||
TEST_FIELD_EQUALITY(v[0], w[0], s2);
|
||||
TEST_FIELD_EQUALITY(v[0], w[0], s3);
|
||||
TEST_FIELD_EQUALITY(v[0], w[0], i);
|
||||
TEST_FIELD_EQUALITY(v[0], w[0], c);
|
||||
|
||||
TEST_SCOPED_ENUM_EQUALITY(v[0], w[0], e);
|
||||
TEST_SCOPED_ENUM_EQUALITY(v[0], w[0], f);
|
||||
|
||||
TEST_FIELD_EQUALITY(v[1], w[1], s1);
|
||||
TEST_FIELD_EQUALITY(v[1], w[1], s2);
|
||||
TEST_FIELD_EQUALITY(v[1], w[1], s3);
|
||||
TEST_FIELD_EQUALITY(v[1], w[1], i);
|
||||
TEST_FIELD_EQUALITY(v[1], w[1], c);
|
||||
|
||||
TEST_SCOPED_ENUM_EQUALITY(v[1], w[1], e);
|
||||
TEST_SCOPED_ENUM_EQUALITY(v[1], w[1], f);
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
private:
|
||||
bool equals(const map<string, string> &lhs, const map<string, string> &rhs)
|
||||
{
|
||||
bool eq = lhs.size() == rhs.size() &&
|
||||
equal(lhs.begin(), lhs.end(), rhs.begin(),
|
||||
[](auto &a, auto &b) { return a.first == b.first &&
|
||||
a.second == b.second; });
|
||||
|
||||
if (eq)
|
||||
return true;
|
||||
|
||||
cerr << "lhs:" << endl;
|
||||
for (const auto &pair : lhs)
|
||||
cerr << "- " << pair.first << ": "
|
||||
<< pair.second << endl;
|
||||
|
||||
cerr << "rhs:" << endl;
|
||||
for (const auto &pair : rhs)
|
||||
cerr << "- " << pair.first << ": "
|
||||
<< pair.second << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool equals(const vector<string> &lhs, const vector<string> &rhs)
|
||||
{
|
||||
bool eq = lhs.size() == rhs.size();
|
||||
|
||||
if (!eq) {
|
||||
cerr << "sizes not equal" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < lhs.size(); i++)
|
||||
if (lhs[i] != rhs[i])
|
||||
eq = false;
|
||||
|
||||
if (eq)
|
||||
return true;
|
||||
|
||||
cerr << "lhs:" << endl;
|
||||
for (const auto &str : lhs)
|
||||
cerr << "- " << str << endl;
|
||||
|
||||
cerr << "rhs:" << endl;
|
||||
for (const auto &str : rhs)
|
||||
cerr << "- " << str << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_REGISTER(IPAGeneratedSerializerTest)
|
||||
@@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
# test.mojom-module
|
||||
mojom = custom_target('test_mojom_module',
|
||||
input : 'test.mojom',
|
||||
output : 'test.mojom-module',
|
||||
command : [
|
||||
mojom_parser,
|
||||
'--output-root', meson.project_build_root(),
|
||||
'--input-root', meson.project_source_root(),
|
||||
'--mojoms', '@INPUT@'
|
||||
])
|
||||
|
||||
# test_ipa_interface.h
|
||||
generated_test_header = custom_target('test_ipa_interface_h',
|
||||
input : mojom,
|
||||
output : 'test_ipa_interface.h',
|
||||
depends : mojom_templates,
|
||||
command : [
|
||||
mojom_generator, 'generate',
|
||||
'-g', 'libcamera',
|
||||
'--bytecode_path', mojom_templates_dir,
|
||||
'--libcamera_generate_header',
|
||||
'--libcamera_output_path=@OUTPUT@',
|
||||
'./' +'@INPUT@'
|
||||
])
|
||||
|
||||
# test_ipa_serializer.h
|
||||
generated_test_serializer = custom_target('test_ipa_serializer_h',
|
||||
input : mojom,
|
||||
output : 'test_ipa_serializer.h',
|
||||
depends : mojom_templates,
|
||||
command : [
|
||||
mojom_generator, 'generate',
|
||||
'-g', 'libcamera',
|
||||
'--bytecode_path', mojom_templates_dir,
|
||||
'--libcamera_generate_serializer',
|
||||
'--libcamera_output_path=@OUTPUT@',
|
||||
'./' +'@INPUT@'
|
||||
])
|
||||
@@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
module ipa.test;
|
||||
|
||||
enum IPAOperationCode {
|
||||
IPAOperationNone,
|
||||
IPAOperationInit,
|
||||
IPAOperationStart,
|
||||
IPAOperationStop,
|
||||
};
|
||||
|
||||
[scopedEnum] enum ErrorFlags {
|
||||
Error1 = 0x1,
|
||||
Error2 = 0x2,
|
||||
Error3 = 0x4,
|
||||
Error4 = 0x8,
|
||||
};
|
||||
|
||||
struct IPASettings {};
|
||||
|
||||
struct TestStruct {
|
||||
map<string, string> m;
|
||||
array<string> a;
|
||||
string s1;
|
||||
string s2;
|
||||
int32 i;
|
||||
string s3;
|
||||
IPAOperationCode c;
|
||||
ErrorFlags e;
|
||||
[flags] ErrorFlags f;
|
||||
};
|
||||
|
||||
interface IPATestInterface {
|
||||
init(IPASettings settings) => (int32 ret);
|
||||
start() => (int32 ret);
|
||||
stop();
|
||||
|
||||
test(TestStruct s);
|
||||
};
|
||||
|
||||
interface IPATestEventInterface {
|
||||
dummyEvent(uint32 val);
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
subdir('include/libcamera/ipa')
|
||||
|
||||
exe = executable('generated_serializer_test',
|
||||
[
|
||||
'generated_serializer_test.cpp',
|
||||
generated_test_header,
|
||||
generated_test_serializer,
|
||||
],
|
||||
dependencies : libcamera_private,
|
||||
link_with : test_libraries,
|
||||
include_directories : [
|
||||
test_includes_internal,
|
||||
'./include',
|
||||
])
|
||||
|
||||
test('generated_serializer_test', exe,
|
||||
suite : 'generated_serializer', is_parallel : false)
|
||||
@@ -0,0 +1,436 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2020, Google Inc.
|
||||
*
|
||||
* Test serializing/deserializing with IPADataSerializer
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cxxabi.h>
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <tuple>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#include <libcamera/base/thread.h>
|
||||
#include <libcamera/base/timer.h>
|
||||
|
||||
#include "libcamera/internal/ipa_data_serializer.h"
|
||||
|
||||
#include "serialization_test.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace libcamera;
|
||||
|
||||
static const ControlInfoMap Controls = ControlInfoMap({
|
||||
{ &controls::AeEnable, ControlInfo(false, true) },
|
||||
{ &controls::ExposureTime, ControlInfo(0, 999999) },
|
||||
{ &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },
|
||||
{ &controls::ColourGains, ControlInfo(0.0f, 32.0f) },
|
||||
{ &controls::Brightness, ControlInfo(-1.0f, 1.0f) },
|
||||
}, controls::controls);
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
static bool operator==(const ControlInfoMap &lhs, const ControlInfoMap &rhs)
|
||||
{
|
||||
return SerializationTest::equals(lhs, rhs);
|
||||
}
|
||||
|
||||
} /* namespace libcamera */
|
||||
|
||||
template<typename T>
|
||||
int testPodSerdes(T in)
|
||||
{
|
||||
std::vector<uint8_t> buf;
|
||||
std::vector<SharedFD> fds;
|
||||
|
||||
std::tie(buf, fds) = IPADataSerializer<T>::serialize(in);
|
||||
T out = IPADataSerializer<T>::deserialize(buf, fds);
|
||||
if (in == out)
|
||||
return TestPass;
|
||||
|
||||
char *name = abi::__cxa_demangle(typeid(T).name(), nullptr,
|
||||
nullptr, nullptr);
|
||||
cerr << "Deserialized " << name << " doesn't match original" << endl;
|
||||
free(name);
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int testVectorSerdes(const std::vector<T> &in,
|
||||
ControlSerializer *cs = nullptr)
|
||||
{
|
||||
std::vector<uint8_t> buf;
|
||||
std::vector<SharedFD> fds;
|
||||
|
||||
std::tie(buf, fds) = IPADataSerializer<std::vector<T>>::serialize(in, cs);
|
||||
std::vector<T> out = IPADataSerializer<std::vector<T>>::deserialize(buf, fds, cs);
|
||||
if (in == out)
|
||||
return TestPass;
|
||||
|
||||
char *name = abi::__cxa_demangle(typeid(T).name(), nullptr,
|
||||
nullptr, nullptr);
|
||||
cerr << "Deserialized std::vector<" << name
|
||||
<< "> doesn't match original" << endl;
|
||||
free(name);
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
int testMapSerdes(const std::map<K, V> &in,
|
||||
ControlSerializer *cs = nullptr)
|
||||
{
|
||||
std::vector<uint8_t> buf;
|
||||
std::vector<SharedFD> fds;
|
||||
|
||||
std::tie(buf, fds) = IPADataSerializer<std::map<K, V>>::serialize(in, cs);
|
||||
std::map<K, V> out = IPADataSerializer<std::map<K, V>>::deserialize(buf, fds, cs);
|
||||
if (in == out)
|
||||
return TestPass;
|
||||
|
||||
char *nameK = abi::__cxa_demangle(typeid(K).name(), nullptr,
|
||||
nullptr, nullptr);
|
||||
char *nameV = abi::__cxa_demangle(typeid(V).name(), nullptr,
|
||||
nullptr, nullptr);
|
||||
cerr << "Deserialized std::map<" << nameK << ", " << nameV
|
||||
<< "> doesn't match original" << endl;
|
||||
free(nameK);
|
||||
free(nameV);
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
class IPADataSerializerTest : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
IPADataSerializerTest()
|
||||
: CameraTest("platform/vimc.0 Sensor B")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
int init() override
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
int run() override
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = testControls();
|
||||
if (ret != TestPass)
|
||||
return ret;
|
||||
|
||||
ret = testVector();
|
||||
if (ret != TestPass)
|
||||
return ret;
|
||||
|
||||
ret = testMap();
|
||||
if (ret != TestPass)
|
||||
return ret;
|
||||
|
||||
ret = testPod();
|
||||
if (ret != TestPass)
|
||||
return ret;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
private:
|
||||
ControlList generateControlList(const ControlInfoMap &infoMap)
|
||||
{
|
||||
/* Create a control list with three controls. */
|
||||
ControlList list(infoMap);
|
||||
|
||||
list.set(controls::Brightness, 0.5f);
|
||||
list.set(controls::Contrast, 1.2f);
|
||||
list.set(controls::Saturation, 0.2f);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
int testControls()
|
||||
{
|
||||
ControlSerializer cs(ControlSerializer::Role::Proxy);
|
||||
|
||||
const ControlInfoMap &infoMap = camera_->controls();
|
||||
ControlList list = generateControlList(infoMap);
|
||||
|
||||
std::vector<uint8_t> infoMapBuf;
|
||||
std::tie(infoMapBuf, std::ignore) =
|
||||
IPADataSerializer<ControlInfoMap>::serialize(infoMap, &cs);
|
||||
|
||||
std::vector<uint8_t> listBuf;
|
||||
std::tie(listBuf, std::ignore) =
|
||||
IPADataSerializer<ControlList>::serialize(list, &cs);
|
||||
|
||||
const ControlInfoMap infoMapOut =
|
||||
IPADataSerializer<ControlInfoMap>::deserialize(infoMapBuf, &cs);
|
||||
|
||||
ControlList listOut = IPADataSerializer<ControlList>::deserialize(listBuf, &cs);
|
||||
|
||||
if (!SerializationTest::equals(infoMap, infoMapOut)) {
|
||||
cerr << "Deserialized map doesn't match original" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (!SerializationTest::equals(list, listOut)) {
|
||||
cerr << "Deserialized list doesn't match original" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int testVector()
|
||||
{
|
||||
ControlSerializer cs(ControlSerializer::Role::Proxy);
|
||||
|
||||
/*
|
||||
* We don't test SharedFD serdes because it dup()s, so we
|
||||
* can't check for equality.
|
||||
*/
|
||||
std::vector<uint8_t> vecUint8 = { 1, 2, 3, 4, 5, 6 };
|
||||
std::vector<uint16_t> vecUint16 = { 1, 2, 3, 4, 5, 6 };
|
||||
std::vector<uint32_t> vecUint32 = { 1, 2, 3, 4, 5, 6 };
|
||||
std::vector<uint64_t> vecUint64 = { 1, 2, 3, 4, 5, 6 };
|
||||
std::vector<int8_t> vecInt8 = { 1, 2, 3, -4, 5, -6 };
|
||||
std::vector<int16_t> vecInt16 = { 1, 2, 3, -4, 5, -6 };
|
||||
std::vector<int32_t> vecInt32 = { 1, 2, 3, -4, 5, -6 };
|
||||
std::vector<int64_t> vecInt64 = { 1, 2, 3, -4, 5, -6 };
|
||||
std::vector<float> vecFloat = { 1.1, 2.2, 3.3, -4.4, 5.5, -6.6 };
|
||||
std::vector<double> vecDouble = { 1.1, 2.2, 3.3, -4.4, 5.5, -6.6 };
|
||||
std::vector<bool> vecBool = { true, true, false, false, true, false };
|
||||
std::vector<std::string> vecString = { "foo", "bar", "baz" };
|
||||
std::vector<ControlInfoMap> vecControlInfoMap = {
|
||||
camera_->controls(),
|
||||
Controls,
|
||||
};
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
std::vector<SharedFD> fds;
|
||||
|
||||
if (testVectorSerdes(vecUint8) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecUint16) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecUint32) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecUint64) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecInt8) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecInt16) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecInt32) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecInt64) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecFloat) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecDouble) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecBool) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecString) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testVectorSerdes(vecControlInfoMap, &cs) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int testMap()
|
||||
{
|
||||
ControlSerializer cs(ControlSerializer::Role::Proxy);
|
||||
|
||||
/*
|
||||
* Realistically, only string and integral keys.
|
||||
* Test simple, complex, and nested compound value.
|
||||
*/
|
||||
std::map<uint64_t, std::string> mapUintStr =
|
||||
{ { 101, "foo" }, { 102, "bar" }, { 103, "baz" } };
|
||||
std::map<int64_t, std::string> mapIntStr =
|
||||
{ { 101, "foo" }, { -102, "bar" }, { -103, "baz" } };
|
||||
std::map<std::string, std::string> mapStrStr =
|
||||
{ { "a", "foo" }, { "b", "bar" }, { "c", "baz" } };
|
||||
std::map<uint64_t, ControlInfoMap> mapUintCIM =
|
||||
{ { 201, camera_->controls() }, { 202, Controls } };
|
||||
std::map<int64_t, ControlInfoMap> mapIntCIM =
|
||||
{ { 201, camera_->controls() }, { -202, Controls } };
|
||||
std::map<std::string, ControlInfoMap> mapStrCIM =
|
||||
{ { "a", camera_->controls() }, { "b", Controls } };
|
||||
std::map<uint64_t, std::vector<uint8_t>> mapUintBVec =
|
||||
{ { 301, { 1, 2, 3 } }, { 302, { 4, 5, 6 } }, { 303, { 7, 8, 9 } } };
|
||||
std::map<int64_t, std::vector<uint8_t>> mapIntBVec =
|
||||
{ { 301, { 1, 2, 3 } }, { -302, { 4, 5, 6} }, { -303, { 7, 8, 9 } } };
|
||||
std::map<std::string, std::vector<uint8_t>> mapStrBVec =
|
||||
{ { "a", { 1, 2, 3 } }, { "b", { 4, 5, 6 } }, { "c", { 7, 8, 9 } } };
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
std::vector<SharedFD> fds;
|
||||
|
||||
if (testMapSerdes(mapUintStr) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapIntStr) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapStrStr) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapUintCIM, &cs) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapIntCIM, &cs) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapStrCIM, &cs) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapUintBVec) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapIntBVec) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testMapSerdes(mapStrBVec) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int testPod()
|
||||
{
|
||||
uint32_t u32min = std::numeric_limits<uint32_t>::min();
|
||||
uint32_t u32max = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t u32one = 1;
|
||||
int32_t i32min = std::numeric_limits<int32_t>::min();
|
||||
int32_t i32max = std::numeric_limits<int32_t>::max();
|
||||
int32_t i32one = 1;
|
||||
|
||||
uint64_t u64min = std::numeric_limits<uint64_t>::min();
|
||||
uint64_t u64max = std::numeric_limits<uint64_t>::max();
|
||||
uint64_t u64one = 1;
|
||||
int64_t i64min = std::numeric_limits<int64_t>::min();
|
||||
int64_t i64max = std::numeric_limits<int64_t>::max();
|
||||
int64_t i64one = 1;
|
||||
|
||||
float flow = std::numeric_limits<float>::lowest();
|
||||
float fmin = std::numeric_limits<float>::min();
|
||||
float fmax = std::numeric_limits<float>::max();
|
||||
float falmostOne = 1 + 1.0e-37;
|
||||
double dlow = std::numeric_limits<double>::lowest();
|
||||
double dmin = std::numeric_limits<double>::min();
|
||||
double dmax = std::numeric_limits<double>::max();
|
||||
double dalmostOne = 1 + 1.0e-307;
|
||||
|
||||
bool t = true;
|
||||
bool f = false;
|
||||
|
||||
std::stringstream ss;
|
||||
for (unsigned int i = 0; i < (1 << 11); i++)
|
||||
ss << "0123456789";
|
||||
|
||||
std::string strLong = ss.str();
|
||||
std::string strEmpty = "";
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
std::vector<SharedFD> fds;
|
||||
|
||||
if (testPodSerdes(u32min) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(u32max) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(u32one) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(i32min) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(i32max) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(i32one) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(u64min) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(u64max) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(u64one) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(i64min) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(i64max) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(i64one) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(flow) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(fmin) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(fmax) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(falmostOne) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(dlow) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(dmin) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(dmax) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(dalmostOne) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(t) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(f) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(strLong) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
if (testPodSerdes(strEmpty) != TestPass)
|
||||
return TestFail;
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_REGISTER(IPADataSerializerTest)
|
||||
16
spider-cam/libcamera/test/serialization/meson.build
Normal file
16
spider-cam/libcamera/test/serialization/meson.build
Normal file
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
subdir('generated_serializer')
|
||||
|
||||
serialization_tests = [
|
||||
{'name': 'control_serialization', 'sources': ['control_serialization.cpp']},
|
||||
{'name': 'ipa_data_serializer_test', 'sources': ['ipa_data_serializer_test.cpp']},
|
||||
]
|
||||
|
||||
foreach test : serialization_tests
|
||||
exe = executable(test['name'], test['sources'], 'serialization_test.cpp',
|
||||
dependencies : libcamera_private,
|
||||
link_with : test_libraries,
|
||||
include_directories : test_includes_internal)
|
||||
test(test['name'], exe, suite : 'serialization', is_parallel : false)
|
||||
endforeach
|
||||
@@ -0,0 +1,89 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* 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, ControlInfo> 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, ControlInfo> 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;
|
||||
}
|
||||
29
spider-cam/libcamera/test/serialization/serialization_test.h
Normal file
29
spider-cam/libcamera/test/serialization/serialization_test.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* Base class for serialization tests
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libcamera/camera.h>
|
||||
#include <libcamera/camera_manager.h>
|
||||
#include <libcamera/controls.h>
|
||||
|
||||
#include "camera_test.h"
|
||||
#include "test.h"
|
||||
|
||||
class SerializationTest : public CameraTest, public Test
|
||||
{
|
||||
public:
|
||||
SerializationTest()
|
||||
: CameraTest("platform/vimc.0 Sensor B")
|
||||
{
|
||||
}
|
||||
|
||||
static bool equals(const libcamera::ControlInfoMap &lhs,
|
||||
const libcamera::ControlInfoMap &rhs);
|
||||
static bool equals(const libcamera::ControlList &lhs,
|
||||
const libcamera::ControlList &rhs);
|
||||
};
|
||||
Reference in New Issue
Block a user