[{"id":14402,"web_url":"https://patchwork.libcamera.org/comment/14402/","msgid":"<X+ufpZdARKGKEJ9I@oden.dyn.berto.se>","date":"2020-12-29T21:29:09","subject":"Re: [libcamera-devel] [PATCH v6 1/4] tests: Add IPADataSerializer\n\ttest","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Paul,\n\nThanks for your test.\n\nOn 2020-12-24 17:17:10 +0900, Paul Elder wrote:\n> Test the IPADataSerializer for controls, vectors, maps, and PODs of\n> built-in types.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> \n> ---\n> Change since v6:\n> - no longer need to initialize rpi ControlInfoMap\n> - no longer need to pass ControlInfoMap to the ControlList serializer\n> \n> Changes in v5:\n> - use ControlInfoMap serializer instead of const ControlInfoMap\n>   serializer\n> \n> Changes in v4:\n> - use RPi::controls instead RPi::Controls\n> \n> Changes in v3:\n> - use re-namespaced RPi::Controls\n> \n> New in v2\n> ---\n>  .../ipa_data_serializer_test.cpp              | 464 ++++++++++++++++++\n>  test/serialization/meson.build                |   3 +-\n>  2 files changed, 466 insertions(+), 1 deletion(-)\n>  create mode 100644 test/serialization/ipa_data_serializer_test.cpp\n> \n> diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp\n> new file mode 100644\n> index 00000000..914663ca\n> --- /dev/null\n> +++ b/test/serialization/ipa_data_serializer_test.cpp\n> @@ -0,0 +1,464 @@\n> +/* SPDX-License-Identifier: GPL-2.0-or-later */\n> +/*\n> + * Copyright (C) 2020, Google Inc.\n> + *\n> + * ipa_data_serializer_test.cpp - Test serializing/deserializing with IPADataSerializer\n> + */\n> +\n> +#include <algorithm>\n> +#include <fcntl.h>\n> +#include <iostream>\n> +#include <limits>\n> +#include <string.h>\n> +#include <sys/stat.h>\n> +#include <sys/types.h>\n> +#include <tuple>\n> +#include <unistd.h>\n> +#include <vector>\n> +\n> +#include <libcamera/ipa/raspberrypi.h>\n> +\n> +#include \"libcamera/internal/device_enumerator.h\"\n> +#include \"libcamera/internal/ipa_data_serializer.h\"\n> +#include \"libcamera/internal/ipa_manager.h\"\n> +#include \"libcamera/internal/ipa_module.h\"\n> +#include \"libcamera/internal/pipeline_handler.h\"\n> +#include \"libcamera/internal/thread.h\"\n> +#include \"libcamera/internal/timer.h\"\n> +\n> +#include \"serialization_test.h\"\n> +#include \"test.h\"\n> +\n> +using namespace std;\n> +using namespace libcamera;\n> +\n> +template<typename T>\n> +bool isVectorEqual(vector<T> &vecA, vector<T> &vecB)\n> +{\n> +\tif (vecA.size() != vecB.size())\n> +\t\treturn false;\n> +\n> +\tsize_t len = vecA.size();\n> +\tfor (unsigned int i = 0; i < len; i++)\n> +\t\tif (vecA[i] != vecB[i])\n> +\t\t\tgoto nequal;\n> +\n> +\treturn true;\n> +\n> +nequal:\n> +\tcerr << \"lhs: { \";\n> +\tfor (const auto &value : vecA)\n> +\t\tcerr << value << \", \";\n> +\tcerr << \"}\" << endl;\n> +\n> +\tcerr << \"rhs: { \";\n> +\tfor (const auto &value : vecB)\n> +\t\tcerr << value << \", \";\n> +\tcerr << \"}\" << endl;\n\nI don't think it's needed to print the vectors if the test fails, as it \nshould not happen after development is done right ;-) If you feel \nstrongly about it I think all vector compare functions should print on \nfail.\n\n> +\n> +\treturn false;\n> +}\n> +\n> +template<>\n> +bool isVectorEqual<ControlInfoMap>(vector<ControlInfoMap> &vecA,\n> +\t\t\t\t   vector<ControlInfoMap> &vecB)\n> +{\n> +\tif (vecA.size() != vecB.size())\n> +\t\treturn false;\n> +\n> +\tsize_t len = vecA.size();\n> +\tfor (unsigned int i = 0; i < len; i++)\n> +\t\tif (!SerializationTest::equals(vecA[i], vecB[i]))\n> +\t\t\treturn false;\n> +\n> +\treturn true;\n> +}\n> +\n> +template<typename K, typename V>\n> +bool isMapEqual(map<K, V> &mapA, map<K, V> &mapB)\n> +{\n> +\tif (mapA == mapB)\n> +\t\treturn true;\n> +\n> +\tcerr << \"lhs: { \";\n> +\tfor (const auto &value : mapA)\n> +\t\tcerr << value.first << \" : \" << value.second << \", \";\n> +\tcerr << \"}\" << endl;\n> +\n> +\tcerr << \"rhs: { \";\n> +\tfor (const auto &value : mapB)\n> +\t\tcerr << value.first << \" : \" << value.second << \", \";\n> +\tcerr << \"}\" << endl;\n\nSame comment as above about printing on failure.\n\n> +\n> +\treturn false;\n> +}\n> +\n> +template<typename K, typename V>\n> +bool isMapToCimEqual(map<K, V> &mapA, map<K, V> &mapB)\n> +{\n> +\tbool isEqual = true;\n> +\n> +\tauto itA = mapA.begin();\n> +\tauto itB = mapB.begin();\n> +\twhile (true) {\n> +\t\tbool endA = (itA == mapA.end());\n> +\t\tbool endB = (itB == mapB.end());\n\nI think you could check mapA.size() != mapB.size() before the loop to \nremove the need for these flags.\n\n> +\n> +\t\tif (endA and endB)\n> +\t\t\tbreak;\n> +\n> +\t\tif (!endA && (endB || itA->first < itB->first)) {\n> +\t\t\tcerr << \"key: \" << itA->first << \" not in mapB\" << endl;\n> +\t\t\tisEqual = false;\n> +\t\t\titA++;\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tif (endA || itB->first < itA->first) {\n> +\t\t\tcerr << \"key: \" << itB->first << \" not in mapA\" << endl;\n> +\t\t\tisEqual = false;\n> +\t\t\titB++;\n> +\t\t\tcontinue;\n> +\t\t}\n> +\n> +\t\tif (!SerializationTest::equals(itA->second, itB->second)) {\n> +\t\t\tcerr << \"key \" << itA->first\n> +\t\t\t     << \" has different values\" << endl;\n> +\t\t\tisEqual = false;\n> +\t\t}\n> +\n> +\t\titA++;\n> +\t\titB++;\n> +\t}\n> +\n> +\treturn isEqual;\n\nWould it make sens to do redice this funnction to something like this \n(not tested)?\n\n    if (mapA.size() != mapB.size())\n        return false;\n\n    for (cont auto &itA : mapA) {\n        itB = mapB.find(itA->first);\n\n        if (itB == mapB.end())\n            return false;\n\n        if (!SerializationTest::equals(itA->second, itB->second))\n            return false;\n    }\n\n    return true;\n\n> +}\n> +\n> +template<typename K, typename V>\n> +bool isMapToVecEqual(map<K, V> &mapA, map<K, V> &mapB)\n> +{\n> +\tif (mapA == mapB)\n> +\t\treturn true;\n> +\n> +\tcerr << \"lhs: { \";\n> +\tfor (const auto &value : mapA) {\n> +\t\tcerr << value.first << \" : { \";\n> +\t\tfor (const auto &v : value.second)\n> +\t\t\tcerr << v << \", \";\n> +\t\tcerr << \"}\" << endl;\n> +\t}\n> +\tcerr << \"}\" << endl;\n> +\n> +\tcerr << \"rhs: { \";\n> +\tfor (const auto &value : mapB) {\n> +\t\tcerr << value.first << \" : { \";\n> +\t\tfor (const auto &v : value.second)\n> +\t\t\tcerr << v << \", \";\n> +\t\tcerr << \"}\" << endl;\n> +\t}\n> +\tcerr << \"}\" << endl;\n\nPrint or no print on fail ;-)\n\n> +\n> +\treturn false;\n> +}\n> +\n> +class IPADataSerializerTest : public CameraTest, public Test\n> +{\n> +public:\n> +\tIPADataSerializerTest()\n> +\t\t: CameraTest(\"platform/vimc.0 Sensor B\")\n> +\t{\n> +\t}\n> +\n> +protected:\n> +\tint init() override\n> +\t{\n> +\t\treturn status_;\n> +\t}\n> +\n> +\tint run() override\n> +\t{\n> +\t\tint finalRet = TestPass;\n> +\t\tint ret;\n> +\n> +\t\tret = testControls();\n> +\t\tif (ret != TestPass)\n> +\t\t\tfinalRet = ret;\n> +\n> +\t\tret = testVector();\n> +\t\tif (ret != TestPass)\n> +\t\t\tfinalRet = ret;\n> +\n> +\t\tret = testMap();\n> +\t\tif (ret != TestPass)\n> +\t\t\tfinalRet = ret;\n> +\n> +\t\tret = testPod();\n> +\t\tif (ret != TestPass)\n> +\t\t\tfinalRet = ret;\n> +\n> +\t\treturn finalRet;\n\nI think it's OK to fail as early as possible and just drop the finalRet \nvariable.\n\n> +\t}\n> +\n> +private:\n> +\tControlList generateControlListA()\n> +\t{\n> +\t\t/* Create a control list with three controls. */\n> +\t\tconst ControlInfoMap &infoMap = camera_->controls();\n> +\t\tControlList list(infoMap);\n\nnit: You could post the infoMap as an argument as you fetch it just \nbefore the only caller.\n\n> +\n> +\t\tlist.set(controls::Brightness, 0.5f);\n> +\t\tlist.set(controls::Contrast, 1.2f);\n> +\t\tlist.set(controls::Saturation, 0.2f);\n> +\n> +\t\treturn list;\n> +\t}\n> +\n> +\tint testControls()\n> +\t{\n> +\t\tControlSerializer cs;\n> +\n> +\t\tconst ControlInfoMap &infoMap = camera_->controls();\n> +\t\tControlList list = generateControlListA();\n> +\n> +\t\tvector<uint8_t> infoMapBuf;\n> +\t\ttie(infoMapBuf, ignore) =\n> +\t\t\tIPADataSerializer<ControlInfoMap>::serialize(infoMap, &cs);\n> +\n> +\t\tvector<uint8_t> listBuf;\n> +\t\ttie(listBuf, ignore) =\n> +\t\t\tIPADataSerializer<ControlList>::serialize(list, &cs);\n> +\n> +\t\tconst ControlInfoMap infoMapOut =\n> +\t\t\tIPADataSerializer<ControlInfoMap>::deserialize(infoMapBuf, &cs);\n> +\n> +\t\tControlList listOut = IPADataSerializer<ControlList>::deserialize(listBuf, &cs);\n> +\n> +\t\tif (!SerializationTest::equals(infoMap, infoMapOut)) {\n> +\t\t\tcerr << \"Deserialized map doesn't match original\" << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tif (!SerializationTest::equals(list, listOut)) {\n> +\t\t\tcerr << \"Deserialized list doesn't match original\" << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\treturn TestPass;\n> +\t}\n> +\n> +\tint testVector()\n> +\t{\n> +\n> +#define TEST_VEC_SERDES(type, vec, cs)\t\t\t\t\t\\\n> +tie(buf, fds) = IPADataSerializer<vector<type>>::serialize(vec, cs);\t\\\n> +vector<type> vec##Out =\t\t\t\t\t\t\t\\\n> +\tIPADataSerializer<vector<type>>::deserialize(buf, fds, cs);\t\\\n> +ret = isVectorEqual<type>(vec, vec##Out);\t\t\t\t\\\n> +if (!ret) {\t\t\t\t\t\t\t\t\\\n> +\tcerr << \"Deserialized vector \" << #vec << \" doesn't match original\" << endl;\\\n> +\tfinalRet = TestFail;\t\t\t\t\t\t\\\n\nI would fail early here with a 'return TestFail'.\n\n> +}\n> +\n> +\t\tControlSerializer cs;\n> +\n> +\t\t/*\n> +\t\t * We don't test FileDescriptor serdes because it dup()s, so we\n> +\t\t * can't check for equality.\n> +\t\t */\n> +\t\tvector<uint8_t>  vecUint8  = { 1, 2, 3, 4, 5, 6 };\n> +\t\tvector<uint16_t> vecUint16 = { 1, 2, 3, 4, 5, 6 };\n> +\t\tvector<uint32_t> vecUint32 = { 1, 2, 3, 4, 5, 6 };\n> +\t\tvector<uint64_t> vecUint64 = { 1, 2, 3, 4, 5, 6 };\n> +\t\tvector<int8_t>   vecInt8   = { 1, 2, 3, -4, 5, -6 };\n> +\t\tvector<int16_t>  vecInt16  = { 1, 2, 3, -4, 5, -6 };\n> +\t\tvector<int32_t>  vecInt32  = { 1, 2, 3, -4, 5, -6 };\n> +\t\tvector<int64_t>  vecInt64  = { 1, 2, 3, -4, 5, -6 };\n> +\t\tvector<float>    vecFloat  = { 1.1, 2.2, 3.3, -4.4, 5.5, -6.6 };\n> +\t\tvector<double>   vecDouble = { 1.1, 2.2, 3.3, -4.4, 5.5, -6.6 };\n> +\t\tvector<bool>     vecBool   = { true, true, false, false, true, false };\n> +\t\tvector<string>   vecString = { \"foo\", \"bar\", \"baz\" };\n> +\t\tvector<ControlInfoMap> vecControlInfoMap = {\n> +\t\t\tcamera_->controls(),\n> +\t\t\tRPi::Controls,\n> +\t\t};\n> +\n> +\t\tvector<uint8_t> buf;\n> +\t\tvector<int32_t> fds;\n> +\t\tint finalRet = TestPass;\n> +\t\tint ret;\n> +\n> +\t\tTEST_VEC_SERDES(uint8_t,  vecUint8,  nullptr);\n> +\t\tTEST_VEC_SERDES(uint16_t, vecUint16, nullptr);\n> +\t\tTEST_VEC_SERDES(uint32_t, vecUint32, nullptr);\n> +\t\tTEST_VEC_SERDES(uint64_t, vecUint64, nullptr);\n> +\t\tTEST_VEC_SERDES(int8_t,   vecInt8,   nullptr);\n> +\t\tTEST_VEC_SERDES(int16_t,  vecInt16,  nullptr);\n> +\t\tTEST_VEC_SERDES(int32_t,  vecInt32,  nullptr);\n> +\t\tTEST_VEC_SERDES(int64_t,  vecInt64,  nullptr);\n> +\t\tTEST_VEC_SERDES(float,    vecFloat,  nullptr);\n> +\t\tTEST_VEC_SERDES(double,   vecDouble, nullptr);\n> +\t\tTEST_VEC_SERDES(bool,     vecBool,   nullptr);\n> +\t\tTEST_VEC_SERDES(string,   vecString, nullptr);\n> +\t\tTEST_VEC_SERDES(ControlInfoMap, vecControlInfoMap, &cs);\n> +\n> +\t\treturn finalRet;\n> +\t}\n> +\n> +\tint testMap()\n> +\t{\n> +\n> +#define TEST_MAP_SERDES(ktype, vtype, m, cs)\t\t\t\t\\\n> +tie(buf, fds) = IPADataSerializer<map<ktype, vtype>>::serialize(m, cs);\t\\\n> +map<ktype, vtype> m##Out =\t\t\t\t\t\t\\\n> +\tIPADataSerializer<map<ktype, vtype>>::deserialize(buf, fds, cs);\\\n> +ret = isMapEqual<ktype, vtype>(m, m##Out);\t\t\t\t\\\n> +if (!ret) {\t\t\t\t\t\t\t\t\\\n> +\tcerr << \"Deserialized map \" << #m << \" doesn't match original\" << endl;\\\n> +\tfinalRet = TestFail;\t\t\t\t\t\t\\\n\nSame as above, fail early IMHO.\n\n> +}\n> +\n> +#define TEST_MAP_CIM_SERDES(ktype, vtype, m, cs)\t\t\t\\\n> +tie(buf, fds) = IPADataSerializer<map<ktype, vtype>>::serialize(m, cs);\t\\\n> +map<ktype, vtype> m##Out =\t\t\t\t\t\t\\\n> +\tIPADataSerializer<map<ktype, vtype>>::deserialize(buf, fds, cs);\\\n> +ret = isMapToCimEqual<ktype, vtype>(m, m##Out);\t\t\t\t\\\n> +if (!ret) {\t\t\t\t\t\t\t\t\\\n> +\tcerr << \"Deserialized map \" << #m << \" doesn't match original\" << endl;\\\n> +\tfinalRet = TestFail;\t\t\t\t\t\t\\\n\nDitto.\n\n> +}\n> +\n> +#define TEST_MAP_VEC_SERDES(ktype, vtype, m, cs)\t\t\t\\\n> +tie(buf, fds) = IPADataSerializer<map<ktype, vtype>>::serialize(m, cs);\t\\\n> +map<ktype, vtype> m##Out =\t\t\t\t\t\t\\\n> +\tIPADataSerializer<map<ktype, vtype>>::deserialize(buf, fds, cs);\\\n> +ret = isMapToVecEqual<ktype, vtype>(m, m##Out);\t\t\t\t\\\n> +if (!ret) {\t\t\t\t\t\t\t\t\\\n> +\tcerr << \"Deserialized map \" << #m << \" doesn't match original\" << endl;\\\n> +\tfinalRet = TestFail;\t\t\t\t\t\t\\\n\nDitto.\n\n> +}\n> +\n> +\t\tControlSerializer cs;\n> +\n> +\t\t/*\n> +\t\t * Realistically, only string and integral keys.\n> +\t\t * Test simple, complex, and nested compound value.\n> +\t\t */\n> +\t\tmap<uint64_t, string> mapUintStr =\n> +\t\t\t{ {101, \"foo\"}, {102, \"bar\"}, {103, \"baz\"} };\n> +\t\tmap<int64_t, string> mapIntStr =\n> +\t\t\t{ {101, \"foo\"}, {-102, \"bar\"}, {-103, \"baz\"} };\n> +\t\tmap<string, string> mapStrStr =\n> +\t\t\t{ {\"a\", \"foo\"}, {\"b\", \"bar\"}, {\"c\", \"baz\"} };\n> +\t\tmap<uint64_t, ControlInfoMap> mapUintCIM =\n> +\t\t\t{ {201, camera_->controls()}, {202, RPi::Controls} };\n> +\t\tmap<int64_t, ControlInfoMap> mapIntCIM =\n> +\t\t\t{ {201, camera_->controls()}, {-202, RPi::Controls} };\n> +\t\tmap<string, ControlInfoMap> mapStrCIM =\n> +\t\t\t{ {\"a\", camera_->controls()}, {\"b\", RPi::Controls} };\n> +\t\tmap<uint64_t, vector<uint8_t>> mapUintBVec =\n> +\t\t\t{ {301, { 1, 2, 3 }}, {302, {4, 5, 6}}, {303, {7, 8, 9}} };\n> +\t\tmap<int64_t, vector<uint8_t>> mapIntBVec =\n> +\t\t\t{ {301, { 1, 2, 3 }}, {-302, {4, 5, 6}}, {-303, {7, 8, 9}} };\n> +\t\tmap<string, vector<uint8_t>> mapStrBVec =\n> +\t\t\t{ {\"a\", { 1, 2, 3 }}, {\"b\", {4, 5, 6}}, {\"c\", {7, 8, 9}} };\n> +\n> +\t\tvector<uint8_t> buf;\n> +\t\tvector<int32_t> fds;\n> +\t\tint finalRet = TestPass;\n> +\t\tint ret;\n> +\n> +\t\tTEST_MAP_SERDES(uint64_t, string,          mapUintStr, nullptr);\n> +\t\tTEST_MAP_SERDES(int64_t,  string,          mapIntStr,  nullptr);\n> +\t\tTEST_MAP_SERDES(string,   string,          mapStrStr,  nullptr);\n> +\t\tTEST_MAP_CIM_SERDES(uint64_t, ControlInfoMap,  mapUintCIM, &cs);\n> +\t\tTEST_MAP_CIM_SERDES(int64_t,  ControlInfoMap,  mapIntCIM,  &cs);\n> +\t\tTEST_MAP_CIM_SERDES(string,   ControlInfoMap,  mapStrCIM,  &cs);\n> +\t\tTEST_MAP_VEC_SERDES(uint64_t, vector<uint8_t>, mapUintBVec, nullptr);\n> +\t\tTEST_MAP_VEC_SERDES(int64_t,  vector<uint8_t>, mapIntBVec,  nullptr);\n> +\t\tTEST_MAP_VEC_SERDES(string,   vector<uint8_t>, mapStrBVec,  nullptr);\n> +\n> +\t\treturn finalRet;\n> +\t}\n> +\n> +\tint testPod()\n> +\t{\n> +\n> +#define TEST_POD_SERDES(type, var)\t\t\t\t\\\n> +tie(buf, fds) = IPADataSerializer<type>::serialize(var);\t\\\n> +type var##Out =\t\t\t\t\t\t\t\\\n> +\tIPADataSerializer<type>::deserialize(buf, fds);\t\t\\\n> +ret = (var == var##Out);\t\t\t\t\t\\\n> +if (!ret) {\t\t\t\t\t\t\t\\\n> +\tcerr << \"Deserialized \" << #var << \" as \" << var##Out\t\\\n> +\t     << \", expected \" << var << endl;\t\t\t\\\n> +\tfinalRet = TestFail;\t\t\t\t\t\\\n> +}\n> +\n> +\t\tuint32_t u32min = numeric_limits<uint32_t>::min();\n> +\t\tuint32_t u32max = numeric_limits<uint32_t>::max();\n> +\t\tuint32_t u32one = 1;\n> +\t\tint32_t  i32min = numeric_limits<int32_t>::min();\n> +\t\tint32_t  i32max = numeric_limits<int32_t>::max();\n> +\t\tint32_t  i32one = 1;\n> +\n> +\t\tuint64_t u64min = numeric_limits<uint64_t>::min();\n> +\t\tuint64_t u64max = numeric_limits<uint64_t>::max();\n> +\t\tuint64_t u64one = 1;\n> +\t\tint64_t  i64min = numeric_limits<int64_t>::min();\n> +\t\tint64_t  i64max = numeric_limits<int64_t>::max();\n> +\t\tint64_t  i64one = 1;\n> +\n> +\t\tfloat  flow = numeric_limits<float>::lowest();\n> +\t\tfloat  fmin = numeric_limits<float>::min();\n> +\t\tfloat  fmax = numeric_limits<float>::max();\n> +\t\tfloat  falmostOne = 1 + 1.0e-37;\n> +\t\tdouble dlow = numeric_limits<double>::lowest();\n> +\t\tdouble dmin = numeric_limits<double>::min();\n> +\t\tdouble dmax = numeric_limits<double>::max();\n> +\t\tdouble dalmostOne = 1 + 1.0e-307;\n> +\n> +\t\tbool t = true;\n> +\t\tbool f = false;\n> +\n> +\t\tstringstream ss;\n> +\t\tfor (unsigned int i = 0; i < (1 << 21); i++)\n> +\t\t\tss << \"0123456789\";\n> +\n> +\t\tstring strLong = ss.str();\n> +\t\tstring strEmpty = \"\";\n> +\n> +\t\tvector<uint8_t> buf;\n> +\t\tvector<int32_t> fds;\n> +\t\tint finalRet = TestPass;\n> +\t\tint ret;\n> +\n> +\t\tTEST_POD_SERDES(uint32_t, u32min);\n> +\t\tTEST_POD_SERDES(uint32_t, u32max);\n> +\t\tTEST_POD_SERDES(uint32_t, u32one);\n> +\t\tTEST_POD_SERDES(int32_t,  i32min);\n> +\t\tTEST_POD_SERDES(int32_t,  i32max);\n> +\t\tTEST_POD_SERDES(int32_t,  i32one);\n> +\t\tTEST_POD_SERDES(uint64_t, u64min);\n> +\t\tTEST_POD_SERDES(uint64_t, u64max);\n> +\t\tTEST_POD_SERDES(uint64_t, u64one);\n> +\t\tTEST_POD_SERDES(int64_t,  i64min);\n> +\t\tTEST_POD_SERDES(int64_t,  i64max);\n> +\t\tTEST_POD_SERDES(int64_t,  i64one);\n> +\t\tTEST_POD_SERDES(float,    flow);\n> +\t\tTEST_POD_SERDES(float,    fmin);\n> +\t\tTEST_POD_SERDES(float,    fmax);\n> +\t\tTEST_POD_SERDES(float,    falmostOne);\n> +\t\tTEST_POD_SERDES(double,   dlow);\n> +\t\tTEST_POD_SERDES(double,   dmin);\n> +\t\tTEST_POD_SERDES(double,   dmax);\n> +\t\tTEST_POD_SERDES(double,   dalmostOne);\n> +\t\tTEST_POD_SERDES(bool,     t);\n> +\t\tTEST_POD_SERDES(bool,     f);\n> +\t\tTEST_POD_SERDES(string,   strLong);\n> +\t\tTEST_POD_SERDES(string,   strEmpty);\n> +\n> +\t\treturn finalRet;\n> +\t}\n> +};\n> +\n> +TEST_REGISTER(IPADataSerializerTest)\n> diff --git a/test/serialization/meson.build b/test/serialization/meson.build\n> index a9d9cbcb..c140a31c 100644\n> --- a/test/serialization/meson.build\n> +++ b/test/serialization/meson.build\n> @@ -1,7 +1,8 @@\n>  # SPDX-License-Identifier: CC0-1.0\n>  \n>  serialization_tests = [\n> -    [ 'control_serialization',    'control_serialization.cpp' ],\n> +    [ 'control_serialization',     'control_serialization.cpp' ],\n> +    [ 'ipa_data_serializer_test',  'ipa_data_serializer_test.cpp' ],\n>  ]\n>  \n>  foreach t : serialization_tests\n> -- \n> 2.27.0\n> \n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E19BDC0F1A\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 29 Dec 2020 21:29:13 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4399F615D2;\n\tTue, 29 Dec 2020 22:29:13 +0100 (CET)","from mail-lf1-x12a.google.com (mail-lf1-x12a.google.com\n\t[IPv6:2a00:1450:4864:20::12a])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9D8926031F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 29 Dec 2020 22:29:11 +0100 (CET)","by mail-lf1-x12a.google.com with SMTP id l11so33711527lfg.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 29 Dec 2020 13:29:11 -0800 (PST)","from localhost (h-209-203.A463.priv.bahnhof.se. [155.4.209.203])\n\tby smtp.gmail.com with ESMTPSA id\n\ta7sm5739905lfg.243.2020.12.29.13.29.09\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tTue, 29 Dec 2020 13:29:10 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=ragnatech-se.20150623.gappssmtp.com\n\theader.i=@ragnatech-se.20150623.gappssmtp.com\n\theader.b=\"Xwk+ibxk\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to;\n\tbh=sakQ1p7pYKqh0+KdNQbkUr6fnthNHi1oFnR0Ejk1Xbs=;\n\tb=Xwk+ibxkRire5b0ljlD14NP3g0NEI+7d8BcE9Tx3umZl+8b/xXAibqpx0G2MHwMQLN\n\tbSAoBsJH+ek8MhzqP+lZj4KcvO+Ks5D9L3NKSnrZOvSXIndym4tQ23DxaiQGRBEEA8js\n\t7zlH32aqURO/LDVD7gNs+G62keMaNRnJAYV94iA2rnDqiUsOOwWAExe7nR5pnCVuA/qv\n\tRMzqu7cUSxakOEdJQUcGYJhyAse6gEWT57/0IDTu2SBX3HaTLKoAJrUQdmeJqYDso7Jz\n\trWUpYmGTe7140JuO7/fy0s2HPjyWkIW+twWUI0pYptzQdVLu+g0GKxao+2dCM+MqtuMx\n\tNekw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to;\n\tbh=sakQ1p7pYKqh0+KdNQbkUr6fnthNHi1oFnR0Ejk1Xbs=;\n\tb=DWB/+2n+FKURc7zGr/EBFSJg/0444geVZi7r5wLcIWi9rlrxMmS1lFKNeDPTGMEIs3\n\tMcapUT9g1QmZx7KLT0leY5Qhecn90ojlRY1y9CzUApY4cS5MfaEO0wabC8ZC/rzWYRuE\n\teYKnbsx2iNeN9hTxy4uBLvu2GBB3gfdaU4t2DdSPK+BgfdDDaXumb2+XpaN5zmiatIAx\n\tsArnA4B+LpNpwrUVgj3m/bC/+wOS5DW5K/bluNxPRPF4HB/Yg3k8ze2E1wcZnlkKYMnE\n\tLDCYhB9FosPObvGGbAs8U6/si9qi1jo2Y8/5ACpotCHq0/jNA005FXRexHG0JslOh0+0\n\tmtYg==","X-Gm-Message-State":"AOAM532z69yEP58iX87XNs6TaAh4tKQ6I/CJ5xYiUn4zzrJGRkmxf/8J\n\tEtVHZl5/VKYQ4xISs5+JoQ5wk+jzOkcP8Q==","X-Google-Smtp-Source":"ABdhPJzWCqxwlt5xJ0DG+0ZYNwh7JFicNb6tG4TUKBDmSUkAugE+e/YoVEVfWuuSB4lswlxd5Kkrhg==","X-Received":"by 2002:a19:8c18:: with SMTP id\n\to24mr22927252lfd.121.1609277350809; \n\tTue, 29 Dec 2020 13:29:10 -0800 (PST)","Date":"Tue, 29 Dec 2020 22:29:09 +0100","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Paul Elder <paul.elder@ideasonboard.com>","Message-ID":"<X+ufpZdARKGKEJ9I@oden.dyn.berto.se>","References":"<20201224081713.41742-1-paul.elder@ideasonboard.com>\n\t<20201224081713.41742-2-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20201224081713.41742-2-paul.elder@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v6 1/4] tests: Add IPADataSerializer\n\ttest","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"iso-8859-1\"","Content-Transfer-Encoding":"quoted-printable","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]