[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:25:37 CET 2021


Hi Laurent,

On Tue, Mar 02, 2021 at 03:18:45AM +0200, Laurent Pinchart wrote:
> Hi Paul,
> 
> On Tue, Mar 02, 2021 at 10:13:16AM +0900, paul.elder at ideasonboard.com wrote:
> > On Tue, Mar 02, 2021 at 03:01:36AM +0200, Laurent Pinchart wrote:
> > > 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>.
> 
> Ah good point.
> 
> > 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?
> 
> If it's easy, sure. Otherwise, the empty header is fine, with a comment
> in the file to explain what it's for.

Hold on, the generated header contains the definition of the TestStruct,
that's why we need it ...how did the tests work before then?

I'll move the mojom file and meson generator into the subdir.


Paul

> > > > 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.
> > 
> > > > +
> > > > +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