[libcamera-devel,02/31] test: Add Span test

Message ID 20200229164254.23604-3-laurent.pinchart@ideasonboard.com
State Superseded
Headers show
Series
  • libcamera: Add support for array controls
Related show

Commit Message

Laurent Pinchart Feb. 29, 2020, 4:42 p.m. UTC
Add a compile-only test that exercises the whole Span API, as template
functions are not fully compile-tested when the file is parsed.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 test/meson.build |   1 +
 test/span.cpp    | 177 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 178 insertions(+)
 create mode 100644 test/span.cpp

Comments

Kieran Bingham March 2, 2020, 3:57 p.m. UTC | #1
Hi Laurent,

On 29/02/2020 16:42, Laurent Pinchart wrote:
> Add a compile-only test that exercises the whole Span API, as template
> functions are not fully compile-tested when the file is parsed.

Do we not want any run-time testing ?

If this 'does nothing' I presume the compiler will just optimise it out
in the end? (Not a problem for compile time testing of course, and
speeds up run-time testing as a perk )

> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

I think such a core feature might warrant some actual run-time testing
at some point to make sure it does the right thing, but perhaps that
will become implicit with usage too, and does not detract from the
current testing here..

so

With a small comment below:

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>


> ---
>  test/meson.build |   1 +
>  test/span.cpp    | 177 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 178 insertions(+)
>  create mode 100644 test/span.cpp
> 
> diff --git a/test/meson.build b/test/meson.build
> index daaa1aac926d..92be382bfe41 100644
> --- a/test/meson.build
> +++ b/test/meson.build
> @@ -30,6 +30,7 @@ internal_tests = [
>      ['object',                          'object.cpp'],
>      ['object-invoke',                   'object-invoke.cpp'],
>      ['signal-threads',                  'signal-threads.cpp'],
> +    ['span',                            'span.cpp'],

Shouldn't this go into public_tests ?

Isn't span going to be part of the public API because of it's role in
controls?



>      ['threads',                         'threads.cpp'],
>      ['timer',                           'timer.cpp'],
>      ['timer-thread',                    'timer-thread.cpp'],
> diff --git a/test/span.cpp b/test/span.cpp
> new file mode 100644
> index 000000000000..609749f51b86
> --- /dev/null
> +++ b/test/span.cpp
> @@ -0,0 +1,177 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2020, Google Inc.
> + *
> + * span.cpp - Span tests
> + */
> +
> +#include <array>
> +#include <iostream>
> +#include <vector>
> +
> +#include <libcamera/span.h>
> +
> +#include "test.h"
> +
> +using namespace std;
> +using namespace libcamera;
> +
> +class SpanTest : public Test
> +{
> +protected:
> +	int run()
> +	{
> +		int i[4]{ 1, 2, 3, 4 };
> +		std::array<int, 4> a{ 1, 2, 3, 4 };
> +		const std::array<int, 4> ca{ 1, 2, 3, 4 };
> +		std::vector<int> v{ 1, 2, 3, 4 };
> +		const std::vector<int> cv{ 1, 2, 3, 4 };
> +
> +		/*
> +		 * Compile-test construction and usage of spans with static
> +		 * extent. Commented-out tests are expected not to compile, or
> +		 * to generate undefined behaviour.
> +		 */
> +
> +		Span<int, 0>{};
> +		/* Span<int, 4>{}; */
> +
> +		Span<int, 4>{ &i[0], 4 };
> +		Span<int, 4>{ &i[0], &i[3] };
> +
> +		Span<int, 4>{ i };
> +		/* Span<float, 4>{ i }; */
> +		/* Span<int, 2>{ i }; */
> +
> +		Span<int, 4>{ a };
> +		Span<const int, 4>{ a };
> +		/* Span<float, 4>{ a }; */
> +		/* Span<int, 2>{ a }; */
> +
> +		Span<const int, 4>{ ca };
> +		/* Span<const int, 2>{ ca }; */
> +		/* Span<const float, 4>{ ca }; */
> +		/* Span<int, 4>{ ca }; */
> +
> +		Span<int, 4>{ v };
> +		Span<const int, 4>{ v };
> +		/* Span<float, 4>{ v }; */
> +
> +		Span<const int, 4>{ v };
> +		/* Span<int, 4>{ v }; */
> +		/* Span<const float, 4>{ v }; */
> +
> +		Span<int, 4> staticSpan{ i };
> +		Span<int, 4>{ staticSpan };
> +		Span<const int, 4>{ staticSpan };
> +		/* Span<const int, 2>{ staticSpan }; */
> +
> +		staticSpan = Span<int, 4>{ v };
> +
> +		staticSpan.begin();
> +		staticSpan.cbegin();
> +		staticSpan.end();
> +		staticSpan.cend();
> +		staticSpan.rbegin();
> +		staticSpan.crbegin();
> +		staticSpan.rend();
> +		staticSpan.crend();
> +
> +		staticSpan.front();
> +		staticSpan.back();
> +		staticSpan[0];
> +		staticSpan.data();
> +
> +		staticSpan.size();
> +		staticSpan.size_bytes();
> +
> +		staticSpan.empty();
> +
> +		staticSpan.first<2>();
> +		staticSpan.first(2);
> +		/* staticSpan.first<6>(); */
> +		/* staticSpan.first(6); */
> +		staticSpan.last<2>();
> +		staticSpan.last(2);
> +		/* staticSpan.last<6>(); */
> +		/* staticSpan.last(6); */
> +		staticSpan.subspan<1>();
> +		staticSpan.subspan<1, 2>();
> +		staticSpan.subspan(1);
> +		staticSpan.subspan(1, 2);
> +		/* staticSpan.subspan(2, 4); */
> +
> +		/*
> +		 * Compile-test construction and usage of spans with static
> +		 * extent. Commented-out tests are expected not to compile, or
> +		 * to generate undefined behaviour.
> +		 */
> +
> +		Span<int>{};
> +
> +		Span<int>{ &i[0], 4 };
> +		Span<int>{ &i[0], &i[3] };
> +
> +		Span<int>{ i };
> +		/* Span<float>{ i }; */
> +
> +		Span<int>{ a };
> +		Span<const int>{ a };
> +		/* Span<float>{ a }; */
> +
> +		Span<const int>{ ca };
> +		/* Span<const float>{ca}; */
> +		/* Span<int>{ca}; */
> +
> +		Span<int>{ v };
> +		Span<const int>{ v };
> +		/* Span<float>{ v }; */
> +
> +		Span<const int>{ v };
> +		/* Span<int>{ v }; */
> +		/* Span<const float>{ v }; */
> +
> +		Span<int> dynamicSpan{ i };
> +		Span<int>{ dynamicSpan };
> +		Span<const int>{ dynamicSpan };
> +
> +		dynamicSpan = Span<int>{ a };
> +
> +		dynamicSpan.begin();
> +		dynamicSpan.cbegin();
> +		dynamicSpan.end();
> +		dynamicSpan.cend();
> +		dynamicSpan.rbegin();
> +		dynamicSpan.crbegin();
> +		dynamicSpan.rend();
> +		dynamicSpan.crend();
> +
> +		dynamicSpan.front();
> +		dynamicSpan.back();
> +		dynamicSpan[0];
> +		dynamicSpan.data();
> +
> +		dynamicSpan.size();
> +		dynamicSpan.size_bytes();
> +
> +		dynamicSpan.empty();
> +
> +		dynamicSpan.first<2>();
> +		dynamicSpan.first(2);
> +		/* dynamicSpan.first<6>(); */
> +		/* dynamicSpan.first(6); */
> +		dynamicSpan.last<2>();
> +		dynamicSpan.last(2);
> +		/* dynamicSpan.last<6>(); */
> +		/* dynamicSpan.last(6); */
> +		dynamicSpan.subspan<1>();
> +		dynamicSpan.subspan<1, 2>();
> +		dynamicSpan.subspan(1);
> +		dynamicSpan.subspan(1, 2);
> +		/* dynamicSpan.subspan(2, 4); */
> +
> +		return TestPass;
> +	}
> +};
> +
> +TEST_REGISTER(SpanTest)
>
Laurent Pinchart March 2, 2020, 4:43 p.m. UTC | #2
Hi Kieran,

On Mon, Mar 02, 2020 at 03:57:08PM +0000, Kieran Bingham wrote:
> On 29/02/2020 16:42, Laurent Pinchart wrote:
> > Add a compile-only test that exercises the whole Span API, as template
> > functions are not fully compile-tested when the file is parsed.
> 
> Do we not want any run-time testing ?

Ideally yes, but feel free to submit a patch :-) I think we're fine with
testing the span implementation through its users for now.

> If this 'does nothing' I presume the compiler will just optimise it out
> in the end? (Not a problem for compile time testing of course, and
> speeds up run-time testing as a perk )

Up to the compiler :-)

> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> I think such a core feature might warrant some actual run-time testing
> at some point to make sure it does the right thing, but perhaps that
> will become implicit with usage too, and does not detract from the
> current testing here..

As the implementation is supposed to be C++20-compliant, if we want to
test it, I think we should use test cases from libstdc++ or libc++.

> so
> 
> With a small comment below:
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> > ---
> >  test/meson.build |   1 +
> >  test/span.cpp    | 177 +++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 178 insertions(+)
> >  create mode 100644 test/span.cpp
> > 
> > diff --git a/test/meson.build b/test/meson.build
> > index daaa1aac926d..92be382bfe41 100644
> > --- a/test/meson.build
> > +++ b/test/meson.build
> > @@ -30,6 +30,7 @@ internal_tests = [
> >      ['object',                          'object.cpp'],
> >      ['object-invoke',                   'object-invoke.cpp'],
> >      ['signal-threads',                  'signal-threads.cpp'],
> > +    ['span',                            'span.cpp'],
> 
> Shouldn't this go into public_tests ?
> 
> Isn't span going to be part of the public API because of it's role in
> controls?

You're right, I'll fix that.

> >      ['threads',                         'threads.cpp'],
> >      ['timer',                           'timer.cpp'],
> >      ['timer-thread',                    'timer-thread.cpp'],
> > diff --git a/test/span.cpp b/test/span.cpp
> > new file mode 100644
> > index 000000000000..609749f51b86
> > --- /dev/null
> > +++ b/test/span.cpp
> > @@ -0,0 +1,177 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (C) 2020, Google Inc.
> > + *
> > + * span.cpp - Span tests
> > + */
> > +
> > +#include <array>
> > +#include <iostream>
> > +#include <vector>
> > +
> > +#include <libcamera/span.h>
> > +
> > +#include "test.h"
> > +
> > +using namespace std;
> > +using namespace libcamera;
> > +
> > +class SpanTest : public Test
> > +{
> > +protected:
> > +	int run()
> > +	{
> > +		int i[4]{ 1, 2, 3, 4 };
> > +		std::array<int, 4> a{ 1, 2, 3, 4 };
> > +		const std::array<int, 4> ca{ 1, 2, 3, 4 };
> > +		std::vector<int> v{ 1, 2, 3, 4 };
> > +		const std::vector<int> cv{ 1, 2, 3, 4 };
> > +
> > +		/*
> > +		 * Compile-test construction and usage of spans with static
> > +		 * extent. Commented-out tests are expected not to compile, or
> > +		 * to generate undefined behaviour.
> > +		 */
> > +
> > +		Span<int, 0>{};
> > +		/* Span<int, 4>{}; */
> > +
> > +		Span<int, 4>{ &i[0], 4 };
> > +		Span<int, 4>{ &i[0], &i[3] };
> > +
> > +		Span<int, 4>{ i };
> > +		/* Span<float, 4>{ i }; */
> > +		/* Span<int, 2>{ i }; */
> > +
> > +		Span<int, 4>{ a };
> > +		Span<const int, 4>{ a };
> > +		/* Span<float, 4>{ a }; */
> > +		/* Span<int, 2>{ a }; */
> > +
> > +		Span<const int, 4>{ ca };
> > +		/* Span<const int, 2>{ ca }; */
> > +		/* Span<const float, 4>{ ca }; */
> > +		/* Span<int, 4>{ ca }; */
> > +
> > +		Span<int, 4>{ v };
> > +		Span<const int, 4>{ v };
> > +		/* Span<float, 4>{ v }; */
> > +
> > +		Span<const int, 4>{ v };
> > +		/* Span<int, 4>{ v }; */
> > +		/* Span<const float, 4>{ v }; */
> > +
> > +		Span<int, 4> staticSpan{ i };
> > +		Span<int, 4>{ staticSpan };
> > +		Span<const int, 4>{ staticSpan };
> > +		/* Span<const int, 2>{ staticSpan }; */
> > +
> > +		staticSpan = Span<int, 4>{ v };
> > +
> > +		staticSpan.begin();
> > +		staticSpan.cbegin();
> > +		staticSpan.end();
> > +		staticSpan.cend();
> > +		staticSpan.rbegin();
> > +		staticSpan.crbegin();
> > +		staticSpan.rend();
> > +		staticSpan.crend();
> > +
> > +		staticSpan.front();
> > +		staticSpan.back();
> > +		staticSpan[0];
> > +		staticSpan.data();
> > +
> > +		staticSpan.size();
> > +		staticSpan.size_bytes();
> > +
> > +		staticSpan.empty();
> > +
> > +		staticSpan.first<2>();
> > +		staticSpan.first(2);
> > +		/* staticSpan.first<6>(); */
> > +		/* staticSpan.first(6); */
> > +		staticSpan.last<2>();
> > +		staticSpan.last(2);
> > +		/* staticSpan.last<6>(); */
> > +		/* staticSpan.last(6); */
> > +		staticSpan.subspan<1>();
> > +		staticSpan.subspan<1, 2>();
> > +		staticSpan.subspan(1);
> > +		staticSpan.subspan(1, 2);
> > +		/* staticSpan.subspan(2, 4); */
> > +
> > +		/*
> > +		 * Compile-test construction and usage of spans with static
> > +		 * extent. Commented-out tests are expected not to compile, or
> > +		 * to generate undefined behaviour.
> > +		 */
> > +
> > +		Span<int>{};
> > +
> > +		Span<int>{ &i[0], 4 };
> > +		Span<int>{ &i[0], &i[3] };
> > +
> > +		Span<int>{ i };
> > +		/* Span<float>{ i }; */
> > +
> > +		Span<int>{ a };
> > +		Span<const int>{ a };
> > +		/* Span<float>{ a }; */
> > +
> > +		Span<const int>{ ca };
> > +		/* Span<const float>{ca}; */
> > +		/* Span<int>{ca}; */
> > +
> > +		Span<int>{ v };
> > +		Span<const int>{ v };
> > +		/* Span<float>{ v }; */
> > +
> > +		Span<const int>{ v };
> > +		/* Span<int>{ v }; */
> > +		/* Span<const float>{ v }; */
> > +
> > +		Span<int> dynamicSpan{ i };
> > +		Span<int>{ dynamicSpan };
> > +		Span<const int>{ dynamicSpan };
> > +
> > +		dynamicSpan = Span<int>{ a };
> > +
> > +		dynamicSpan.begin();
> > +		dynamicSpan.cbegin();
> > +		dynamicSpan.end();
> > +		dynamicSpan.cend();
> > +		dynamicSpan.rbegin();
> > +		dynamicSpan.crbegin();
> > +		dynamicSpan.rend();
> > +		dynamicSpan.crend();
> > +
> > +		dynamicSpan.front();
> > +		dynamicSpan.back();
> > +		dynamicSpan[0];
> > +		dynamicSpan.data();
> > +
> > +		dynamicSpan.size();
> > +		dynamicSpan.size_bytes();
> > +
> > +		dynamicSpan.empty();
> > +
> > +		dynamicSpan.first<2>();
> > +		dynamicSpan.first(2);
> > +		/* dynamicSpan.first<6>(); */
> > +		/* dynamicSpan.first(6); */
> > +		dynamicSpan.last<2>();
> > +		dynamicSpan.last(2);
> > +		/* dynamicSpan.last<6>(); */
> > +		/* dynamicSpan.last(6); */
> > +		dynamicSpan.subspan<1>();
> > +		dynamicSpan.subspan<1, 2>();
> > +		dynamicSpan.subspan(1);
> > +		dynamicSpan.subspan(1, 2);
> > +		/* dynamicSpan.subspan(2, 4); */
> > +
> > +		return TestPass;
> > +	}
> > +};
> > +
> > +TEST_REGISTER(SpanTest)

Patch

diff --git a/test/meson.build b/test/meson.build
index daaa1aac926d..92be382bfe41 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -30,6 +30,7 @@  internal_tests = [
     ['object',                          'object.cpp'],
     ['object-invoke',                   'object-invoke.cpp'],
     ['signal-threads',                  'signal-threads.cpp'],
+    ['span',                            'span.cpp'],
     ['threads',                         'threads.cpp'],
     ['timer',                           'timer.cpp'],
     ['timer-thread',                    'timer-thread.cpp'],
diff --git a/test/span.cpp b/test/span.cpp
new file mode 100644
index 000000000000..609749f51b86
--- /dev/null
+++ b/test/span.cpp
@@ -0,0 +1,177 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * span.cpp - Span tests
+ */
+
+#include <array>
+#include <iostream>
+#include <vector>
+
+#include <libcamera/span.h>
+
+#include "test.h"
+
+using namespace std;
+using namespace libcamera;
+
+class SpanTest : public Test
+{
+protected:
+	int run()
+	{
+		int i[4]{ 1, 2, 3, 4 };
+		std::array<int, 4> a{ 1, 2, 3, 4 };
+		const std::array<int, 4> ca{ 1, 2, 3, 4 };
+		std::vector<int> v{ 1, 2, 3, 4 };
+		const std::vector<int> cv{ 1, 2, 3, 4 };
+
+		/*
+		 * Compile-test construction and usage of spans with static
+		 * extent. Commented-out tests are expected not to compile, or
+		 * to generate undefined behaviour.
+		 */
+
+		Span<int, 0>{};
+		/* Span<int, 4>{}; */
+
+		Span<int, 4>{ &i[0], 4 };
+		Span<int, 4>{ &i[0], &i[3] };
+
+		Span<int, 4>{ i };
+		/* Span<float, 4>{ i }; */
+		/* Span<int, 2>{ i }; */
+
+		Span<int, 4>{ a };
+		Span<const int, 4>{ a };
+		/* Span<float, 4>{ a }; */
+		/* Span<int, 2>{ a }; */
+
+		Span<const int, 4>{ ca };
+		/* Span<const int, 2>{ ca }; */
+		/* Span<const float, 4>{ ca }; */
+		/* Span<int, 4>{ ca }; */
+
+		Span<int, 4>{ v };
+		Span<const int, 4>{ v };
+		/* Span<float, 4>{ v }; */
+
+		Span<const int, 4>{ v };
+		/* Span<int, 4>{ v }; */
+		/* Span<const float, 4>{ v }; */
+
+		Span<int, 4> staticSpan{ i };
+		Span<int, 4>{ staticSpan };
+		Span<const int, 4>{ staticSpan };
+		/* Span<const int, 2>{ staticSpan }; */
+
+		staticSpan = Span<int, 4>{ v };
+
+		staticSpan.begin();
+		staticSpan.cbegin();
+		staticSpan.end();
+		staticSpan.cend();
+		staticSpan.rbegin();
+		staticSpan.crbegin();
+		staticSpan.rend();
+		staticSpan.crend();
+
+		staticSpan.front();
+		staticSpan.back();
+		staticSpan[0];
+		staticSpan.data();
+
+		staticSpan.size();
+		staticSpan.size_bytes();
+
+		staticSpan.empty();
+
+		staticSpan.first<2>();
+		staticSpan.first(2);
+		/* staticSpan.first<6>(); */
+		/* staticSpan.first(6); */
+		staticSpan.last<2>();
+		staticSpan.last(2);
+		/* staticSpan.last<6>(); */
+		/* staticSpan.last(6); */
+		staticSpan.subspan<1>();
+		staticSpan.subspan<1, 2>();
+		staticSpan.subspan(1);
+		staticSpan.subspan(1, 2);
+		/* staticSpan.subspan(2, 4); */
+
+		/*
+		 * Compile-test construction and usage of spans with static
+		 * extent. Commented-out tests are expected not to compile, or
+		 * to generate undefined behaviour.
+		 */
+
+		Span<int>{};
+
+		Span<int>{ &i[0], 4 };
+		Span<int>{ &i[0], &i[3] };
+
+		Span<int>{ i };
+		/* Span<float>{ i }; */
+
+		Span<int>{ a };
+		Span<const int>{ a };
+		/* Span<float>{ a }; */
+
+		Span<const int>{ ca };
+		/* Span<const float>{ca}; */
+		/* Span<int>{ca}; */
+
+		Span<int>{ v };
+		Span<const int>{ v };
+		/* Span<float>{ v }; */
+
+		Span<const int>{ v };
+		/* Span<int>{ v }; */
+		/* Span<const float>{ v }; */
+
+		Span<int> dynamicSpan{ i };
+		Span<int>{ dynamicSpan };
+		Span<const int>{ dynamicSpan };
+
+		dynamicSpan = Span<int>{ a };
+
+		dynamicSpan.begin();
+		dynamicSpan.cbegin();
+		dynamicSpan.end();
+		dynamicSpan.cend();
+		dynamicSpan.rbegin();
+		dynamicSpan.crbegin();
+		dynamicSpan.rend();
+		dynamicSpan.crend();
+
+		dynamicSpan.front();
+		dynamicSpan.back();
+		dynamicSpan[0];
+		dynamicSpan.data();
+
+		dynamicSpan.size();
+		dynamicSpan.size_bytes();
+
+		dynamicSpan.empty();
+
+		dynamicSpan.first<2>();
+		dynamicSpan.first(2);
+		/* dynamicSpan.first<6>(); */
+		/* dynamicSpan.first(6); */
+		dynamicSpan.last<2>();
+		dynamicSpan.last(2);
+		/* dynamicSpan.last<6>(); */
+		/* dynamicSpan.last(6); */
+		dynamicSpan.subspan<1>();
+		dynamicSpan.subspan<1, 2>();
+		dynamicSpan.subspan(1);
+		dynamicSpan.subspan(1, 2);
+		/* dynamicSpan.subspan(2, 4); */
+
+		return TestPass;
+	}
+};
+
+TEST_REGISTER(SpanTest)