[libcamera-devel] [PATCH v9 3/3] tests: Test IPA serializer generation

paul.elder at ideasonboard.com paul.elder at ideasonboard.com
Tue Mar 2 02:13:16 CET 2021


Hi Laurent,

On Tue, Mar 02, 2021 at 03:01:36AM +0200, Laurent Pinchart wrote:
> Hi Paul,
> 
> Thank you for the patch.
> 
> On Mon, Mar 01, 2021 at 03:52:26PM +0900, Paul Elder wrote:
> > Add a test to confirm that serializer and header generation works
> > properly for mojom definition files, and that the serializer works
> > properly.
> > 
> > Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > 
> > ---
> > Changes in v9:
> > - rename everything vimc to test
> > - add std:: to vectors and ties
> > 
> > No change in v8
> > 
> > Changes in v7:
> > - add test to test serdes of a vector of *generated* structs
> > 
> > Changes in v6:
> > - use namespacing in the mojom file, and in the test
> > - add the enum to the test mojom file, as vimc.h no longer exists
> > 
> > Changes in v5:
> > - add dummy event to event interface
> > 
> > New in v4
> > ---
> >  .../generated_serializer_test.cpp             | 156 ++++++++++++++++++
> >  .../libcamera/ipa/test_ipa_interface.h        |   0
> >  .../generated_serializer/meson.build          |  52 ++++++
> >  .../generated_serializer/test.mojom           |  33 ++++
> >  test/serialization/meson.build                |   2 +
> >  5 files changed, 243 insertions(+)
> >  create mode 100644 test/serialization/generated_serializer/generated_serializer_test.cpp
> >  create mode 100644 test/serialization/generated_serializer/include/libcamera/ipa/test_ipa_interface.h
> >  create mode 100644 test/serialization/generated_serializer/meson.build
> >  create mode 100644 test/serialization/generated_serializer/test.mojom
> > 
> > diff --git a/test/serialization/generated_serializer/generated_serializer_test.cpp b/test/serialization/generated_serializer/generated_serializer_test.cpp
> > new file mode 100644
> > index 00000000..698c81d6
> > --- /dev/null
> > +++ b/test/serialization/generated_serializer/generated_serializer_test.cpp
> > @@ -0,0 +1,156 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (C) 2020, Google Inc.
> > + *
> > + * generated_serializer_test.cpp - 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;					\
> > +}
> > +
> > +		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;
> > +
> > +		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 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[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);
> > +
> > +		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)
> > diff --git a/test/serialization/generated_serializer/include/libcamera/ipa/test_ipa_interface.h b/test/serialization/generated_serializer/include/libcamera/ipa/test_ipa_interface.h
> > new file mode 100644
> > index 00000000..e69de29b
> 
> Did you mean to add an empty test_ipa_interface.h ?

Yes, I did.

We tell the generator to generate a test_ipa_serializer.h based on
test.mojom, but this generates #include
<libcamera/test_ipa_interface.h>.

Although, below I generate test_ipa_interface.h from test.mojom.

Maybe it's better to mkdir -p
test/serialization/generated_serializer/include/libcamera/ipa and then
put the mojom file and the meson generator there?

> > diff --git a/test/serialization/generated_serializer/meson.build b/test/serialization/generated_serializer/meson.build
> > new file mode 100644
> > index 00000000..aad6c4a1
> > --- /dev/null
> > +++ b/test/serialization/generated_serializer/meson.build
> > @@ -0,0 +1,52 @@
> > +# SPDX-License-Identifier: CC0-1.0
> > +
> > +# vimc.mojom-module

Oh I need to s/vimc/test here and below.

> > +mojom = custom_target('test_mojom_module',
> > +                      input : 'test.mojom',
> > +                      output : 'test.mojom-module',
> > +                      command : [
> > +                          mojom_parser,
> > +                          '--output-root', meson.build_root(),
> > +                          '--input-root', meson.source_root(),
> > +                          '--mojoms', '@INPUT@'
> > +                      ])
> > +
> > +# vimc_test_ipa_interface.h
> > +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@'
> > +                       ])
> > +
> > +# vimc_test_ipa_serializer.h
> > +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@'
> > +                           ])
> > +
> > +exe = executable('generated_serializer_test',
> > +                 ['generated_serializer_test.cpp', header, serializer],
> > +                 dependencies : libcamera_dep,
> > +                 link_with : test_libraries,
> > +                 include_directories : [
> > +                     test_includes_internal,
> > +                     './include',
> > +                 ])
> > +
> > +test('generated_serializer_test', exe,
> > +     suite : 'generated_serializer', is_parallel : false)
> > diff --git a/test/serialization/generated_serializer/test.mojom b/test/serialization/generated_serializer/test.mojom
> > new file mode 100644
> > index 00000000..2fd973e9
> > --- /dev/null
> > +++ b/test/serialization/generated_serializer/test.mojom
> > @@ -0,0 +1,33 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +
> > +module ipa.test;
> > +
> > +enum IPAOperationCode {
> > +	IPAOperationNone,
> > +	IPAOperationInit,
> > +	IPAOperationStart,
> > +	IPAOperationStop,
> > +};
> > +
> > +struct IPASettings {};
> > +
> > +struct TestStruct {
> > +	map<string, string> m;
> > +	array<string> a;
> > +	string s1;
> > +	string s2;
> > +	int32 i;
> > +	string s3;
> > +};
> > +
> > +interface IPAVimcInterface {
> > +	init(IPASettings settings) => (int32 ret);
> > +	start() => (int32 ret);
> > +	stop();
> > +
> > +	test(TestStruct s);
> > +};

Oh I forgot to s/Vimc/Test here and below too.


Paul

> > +
> > +interface IPAVimcEventInterface {
> > +	dummyEvent(uint32 val);
> > +};
> > diff --git a/test/serialization/meson.build b/test/serialization/meson.build
> > index a4636337..60ebf325 100644
> > --- a/test/serialization/meson.build
> > +++ b/test/serialization/meson.build
> > @@ -1,5 +1,7 @@
> >  # SPDX-License-Identifier: CC0-1.0
> >  
> > +subdir('generated_serializer')
> > +
> >  serialization_tests = [
> >      ['control_serialization',     'control_serialization.cpp'],
> >      ['ipa_data_serializer_test',  'ipa_data_serializer_test.cpp'],


More information about the libcamera-devel mailing list