[libcamera-devel,v2,4/4] test: MediaDevice: Add link exercise test

Message ID 20190108170407.4770-5-jacopo@jmondi.org
State Superseded
Headers show
Series
  • libcamera: media device: Add link handling
Related show

Commit Message

Jacopo Mondi Jan. 8, 2019, 5:04 p.m. UTC
Add test function to exercise the link handling abilities of the media
device.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
v1->v2:
- Make the link handling test work only on vimc as operating on a known
  graph makes it possible to identify unexpected results.

 test/media_device/media_device_test.cpp | 147 +++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 4 deletions(-)

--
2.20.1

Comments

Laurent Pinchart Jan. 8, 2019, 6:22 p.m. UTC | #1
Hi Jacopo,

Thank you for the patch.

On Tuesday, 8 January 2019 19:04:07 EET Jacopo Mondi wrote:
> Add test function to exercise the link handling abilities of the media
> device.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
> v1->v2:
> - Make the link handling test work only on vimc as operating on a known
>   graph makes it possible to identify unexpected results.
> 
>  test/media_device/media_device_test.cpp | 147 +++++++++++++++++++++++-
>  1 file changed, 143 insertions(+), 4 deletions(-)
> 
> diff --git a/test/media_device/media_device_test.cpp
> b/test/media_device/media_device_test.cpp index c482b2e..2b2f5cd 100644
> --- a/test/media_device/media_device_test.cpp
> +++ b/test/media_device/media_device_test.cpp
> @@ -42,8 +42,145 @@ private:
>  	void printMediaGraph(const MediaDevice &media, ostream &os);
>  	void printLinkFlags(const MediaLink *link, ostream &os);
>  	void printNode(const MediaPad *pad, ostream &os);
> +
> +	int exerciseLinks(MediaDevice &media);

Especially given how we skip the test if we have a non-vimc device, I thnk 
this should really be part of a separate test class.

>  };
> 
> +/*
> + * Exercise the link handling interface.
> + *
> + * Try to get existing and non-existing links, and try to enable
> + * disable links.
> + *
> + * WARNING: this test only runs on VIMC, as a known media graph allows
> + * the test to exercise known links and verify the result of operations
> + * known to fail or succeed. If the 'vimc' driver is not loaded, the test
> is
> + * skipped.
> + */
> +int MediaDeviceTest::exerciseLinks(MediaDevice &media)
> +{
> +	if (media.driver() != "vimc")
> +		return TestSkip;

This check should be moved to the init() function of the test class.

> +	/* First of all reset all links in the media graph. */
> +	int ret = media.resetLinks();
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Test if link can be consistently retrieved through the different
> +	 * methods the media device offers.
> +	 */
> +	MediaLink *link = media.link("Debayer A", 1, "Scaler", 0);
> +	if (!link) {
> +		cerr << "Unable to find link \"Debayer A\"[1] -> \"Scaler\"[0]"
> +		     << endl << "This link exists in VIMC media graph" << endl;
> +		return TestFail;
> +	}
> +
> +	MediaEntity *source = media.getEntityByName("Debayer A");
> +	if (!source) {
> +		cerr << "Unable to find entity \"Debayer A\"" << endl;
> +		return TestFail;
> +	}
> +
> +	MediaEntity *sink = media.getEntityByName("Scaler");
> +	if (!sink) {
> +		cerr << "Unable to find entity \"Scaler\"" << endl;
> +		return TestFail;
> +	}
> +
> +	MediaLink *link2 = media.link(source, 1, sink, 0);
> +	if (!link2) {
> +		cerr << "Unable to find link \"Debayer A\"[1] -> \"Scaler\"[0]"
> +		     << endl << "This link exists in VIMC media graph" << endl;
> +		return TestFail;
> +	}
> +
> +	if (link != link2) {
> +		cerr << "The returned link does not match what was expected"
> +		     << endl;
> +		return TestFail;
> +	}
> +
> +	link2 = media.link(source->getPadByIndex(1), sink->getPadByIndex(0));
> +	if (!link2) {
> +		cerr << "Unable to find link \"Debayer A\"[1] -> \"Scaler\"[0]"
> +		     << endl << "This link exists in VIMC media graph" << endl;
> +		return TestFail;
> +	}
> +
> +	if (link != link2) {
> +		cerr << "The returned link does not match what was expected"
> +		     << endl;
> +		return TestFail;
> +	}
> +
> +	/* After reset the link shall not be enabled. */
> +	if (link->flags() & MEDIA_LNK_FL_ENABLED) {
> +		cerr << "Link \"Debayer A\"[1] -> \"Scaler\"[0]"
> +		     << " should not be enabled after a media device reset"
> +		     << endl;
> +		return TestFail;
> +	}
> +
> +	/* Enable the link and test if enabling was successful. */
> +	ret = link->setEnable(true);
> +	if (ret)
> +		return TestFail;
> +
> +	if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
> +		cerr << "Link \"Debayer A\"[1] -> \"Scaler\"[0]"
> +		     << " should now be enabled" << endl;
> +		return TestFail;
> +	}
> +
> +	/* Disable the link and test if disabling was successful. */
> +	ret = link->setEnable(false);
> +	if (ret)
> +		return TestFail;
> +
> +	if (link->flags() & MEDIA_LNK_FL_ENABLED) {
> +		cerr << "Link \"Debayer A\"[1] -> \"Scaler\"[0]"
> +		     << " should now be disabled" << endl;
> +		return TestFail;
> +	}
> +
> +	/* Try to get a non existing link. */
> +	link = media.link("Sensor A", 1, "Scaler", 0);
> +	if (link) {
> +		cerr << "Link \"Sensor A\"[1] -> \"Scaler\"[0]"
> +		     << " does not exist but something was returned"
> +		     << endl;
> +		return TestFail;
> +	}
> +
> +	/* Now get an immutable link and try to disable it. */
> +	link = media.link("Sensor A", 0, "Raw Capture 0", 0);
> +	if (!link) {
> +		cerr << "Unable to find link \"Sensor A\"[0] -> "
> +		     << "\"Raw Capture 0\"[0]"
> +		     << endl << "This link exists in VIMC media graph" << endl;
> +		return TestFail;
> +	}
> +
> +	if (!(link->flags() & MEDIA_LNK_FL_IMMUTABLE)) {
> +		cerr << "Link \"Sensor A\"[0] -> \"Raw Capture 0\"[0]"
> +		     << " should have been 'IMMUTABLE'" << endl;
> +		return TestFail;
> +	}
> +
> +	/* Disabling an immutable link shall fail. */
> +	ret = link->setEnable(false);
> +	if (!ret) {
> +		cerr << "Link \"Sensor A\"[0] -> \"Raw Capture 0\"[0]"
> +		     << " is 'IMMUTABLE', it shouldn't be disabled" << endl;
> +		return TestFail;
> +	}
> +
> +	return 0;
> +}
> +
>  void MediaDeviceTest::printNode(const MediaPad *pad, ostream &os)
>  {
>  	const MediaEntity *entity = pad->entity();
> @@ -136,11 +273,14 @@ int MediaDeviceTest::testMediaDevice(const string
> devnode)
> 
>  	/* Run tests in sequence. */
>  	printMediaGraph(dev, cerr);
> +
> +	ret = exerciseLinks(dev);
> +

You should iterate over all the media devices present in the system and pick 
the first vimc device, as it may not be /dev/media0. The device enumerator 
should provide you with the media devices (and this would also serve as a 
device enumerator test :-)).

>  	/* TODO: add more tests here. */
> 
>  	dev.close();
> 
> -	return 0;
> +	return ret;
>  }
> 
>  /* Run tests on all media devices. */
> @@ -149,7 +289,7 @@ int MediaDeviceTest::run()
>  {
>  	const string devnode("/dev/media");
>  	unsigned int i;
> -	int ret = 77; /* skip test exit code */
> +	int ret = TestSkip;
> 
>  	/*
>  	 * Run the test sequence on all media device found in the
> @@ -163,9 +303,8 @@ int MediaDeviceTest::run()
>  			continue;
> 
>  		ret = testMediaDevice(mediadev);
> -		if (ret)
> +		if (ret && ret != TestSkip)
>  			return ret;
> -
>  	}
> 
>  	return ret;

Patch

diff --git a/test/media_device/media_device_test.cpp b/test/media_device/media_device_test.cpp
index c482b2e..2b2f5cd 100644
--- a/test/media_device/media_device_test.cpp
+++ b/test/media_device/media_device_test.cpp
@@ -42,8 +42,145 @@  private:
 	void printMediaGraph(const MediaDevice &media, ostream &os);
 	void printLinkFlags(const MediaLink *link, ostream &os);
 	void printNode(const MediaPad *pad, ostream &os);
+
+	int exerciseLinks(MediaDevice &media);
 };

+/*
+ * Exercise the link handling interface.
+ *
+ * Try to get existing and non-existing links, and try to enable
+ * disable links.
+ *
+ * WARNING: this test only runs on VIMC, as a known media graph allows
+ * the test to exercise known links and verify the result of operations
+ * known to fail or succeed. If the 'vimc' driver is not loaded, the test is
+ * skipped.
+ */
+int MediaDeviceTest::exerciseLinks(MediaDevice &media)
+{
+	if (media.driver() != "vimc")
+		return TestSkip;
+
+	/* First of all reset all links in the media graph. */
+	int ret = media.resetLinks();
+	if (ret)
+		return ret;
+
+	/*
+	 * Test if link can be consistently retrieved through the different
+	 * methods the media device offers.
+	 */
+	MediaLink *link = media.link("Debayer A", 1, "Scaler", 0);
+	if (!link) {
+		cerr << "Unable to find link \"Debayer A\"[1] -> \"Scaler\"[0]"
+		     << endl << "This link exists in VIMC media graph" << endl;
+		return TestFail;
+	}
+
+	MediaEntity *source = media.getEntityByName("Debayer A");
+	if (!source) {
+		cerr << "Unable to find entity \"Debayer A\"" << endl;
+		return TestFail;
+	}
+
+	MediaEntity *sink = media.getEntityByName("Scaler");
+	if (!sink) {
+		cerr << "Unable to find entity \"Scaler\"" << endl;
+		return TestFail;
+	}
+
+	MediaLink *link2 = media.link(source, 1, sink, 0);
+	if (!link2) {
+		cerr << "Unable to find link \"Debayer A\"[1] -> \"Scaler\"[0]"
+		     << endl << "This link exists in VIMC media graph" << endl;
+		return TestFail;
+	}
+
+	if (link != link2) {
+		cerr << "The returned link does not match what was expected"
+		     << endl;
+		return TestFail;
+	}
+
+	link2 = media.link(source->getPadByIndex(1), sink->getPadByIndex(0));
+	if (!link2) {
+		cerr << "Unable to find link \"Debayer A\"[1] -> \"Scaler\"[0]"
+		     << endl << "This link exists in VIMC media graph" << endl;
+		return TestFail;
+	}
+
+	if (link != link2) {
+		cerr << "The returned link does not match what was expected"
+		     << endl;
+		return TestFail;
+	}
+
+	/* After reset the link shall not be enabled. */
+	if (link->flags() & MEDIA_LNK_FL_ENABLED) {
+		cerr << "Link \"Debayer A\"[1] -> \"Scaler\"[0]"
+		     << " should not be enabled after a media device reset"
+		     << endl;
+		return TestFail;
+	}
+
+	/* Enable the link and test if enabling was successful. */
+	ret = link->setEnable(true);
+	if (ret)
+		return TestFail;
+
+	if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
+		cerr << "Link \"Debayer A\"[1] -> \"Scaler\"[0]"
+		     << " should now be enabled" << endl;
+		return TestFail;
+	}
+
+	/* Disable the link and test if disabling was successful. */
+	ret = link->setEnable(false);
+	if (ret)
+		return TestFail;
+
+	if (link->flags() & MEDIA_LNK_FL_ENABLED) {
+		cerr << "Link \"Debayer A\"[1] -> \"Scaler\"[0]"
+		     << " should now be disabled" << endl;
+		return TestFail;
+	}
+
+	/* Try to get a non existing link. */
+	link = media.link("Sensor A", 1, "Scaler", 0);
+	if (link) {
+		cerr << "Link \"Sensor A\"[1] -> \"Scaler\"[0]"
+		     << " does not exist but something was returned"
+		     << endl;
+		return TestFail;
+	}
+
+	/* Now get an immutable link and try to disable it. */
+	link = media.link("Sensor A", 0, "Raw Capture 0", 0);
+	if (!link) {
+		cerr << "Unable to find link \"Sensor A\"[0] -> "
+		     << "\"Raw Capture 0\"[0]"
+		     << endl << "This link exists in VIMC media graph" << endl;
+		return TestFail;
+	}
+
+	if (!(link->flags() & MEDIA_LNK_FL_IMMUTABLE)) {
+		cerr << "Link \"Sensor A\"[0] -> \"Raw Capture 0\"[0]"
+		     << " should have been 'IMMUTABLE'" << endl;
+		return TestFail;
+	}
+
+	/* Disabling an immutable link shall fail. */
+	ret = link->setEnable(false);
+	if (!ret) {
+		cerr << "Link \"Sensor A\"[0] -> \"Raw Capture 0\"[0]"
+		     << " is 'IMMUTABLE', it shouldn't be disabled" << endl;
+		return TestFail;
+	}
+
+	return 0;
+}
+
 void MediaDeviceTest::printNode(const MediaPad *pad, ostream &os)
 {
 	const MediaEntity *entity = pad->entity();
@@ -136,11 +273,14 @@  int MediaDeviceTest::testMediaDevice(const string devnode)

 	/* Run tests in sequence. */
 	printMediaGraph(dev, cerr);
+
+	ret = exerciseLinks(dev);
+
 	/* TODO: add more tests here. */

 	dev.close();

-	return 0;
+	return ret;
 }

 /* Run tests on all media devices. */
@@ -149,7 +289,7 @@  int MediaDeviceTest::run()
 {
 	const string devnode("/dev/media");
 	unsigned int i;
-	int ret = 77; /* skip test exit code */
+	int ret = TestSkip;

 	/*
 	 * Run the test sequence on all media device found in the
@@ -163,9 +303,8 @@  int MediaDeviceTest::run()
 			continue;

 		ret = testMediaDevice(mediadev);
-		if (ret)
+		if (ret && ret != TestSkip)
 			return ret;
-
 	}

 	return ret;