test: media_device: Add link handling test
Add a test unit that exercise link handling on the VIMC media graph. Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
parent
d85767a8c8
commit
d833c1d39e
2 changed files with 247 additions and 0 deletions
246
test/media_device/media_device_link_test.cpp
Normal file
246
test/media_device/media_device_link_test.cpp
Normal file
|
@ -0,0 +1,246 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* media_device_link_test.cpp - Tests link handling on VIMC media device
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "device_enumerator.h"
|
||||
#include "media_device.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* This link test requires a vimc device in order to exercise the
|
||||
* MediaObject link handling API on a graph with a predetermined topology.
|
||||
*
|
||||
* vimc is a Media Controller kernel driver that creates virtual devices.
|
||||
* From a userspace point of view they appear as normal media controller
|
||||
* devices, but are not backed by any particular piece of hardware. They can
|
||||
* thus be used for testing purpose without depending on a particular hardware
|
||||
* platform.
|
||||
*
|
||||
* If no vimc device is found (most likely because the vimc driver is not
|
||||
* loaded) the test is skipped.
|
||||
*/
|
||||
|
||||
class MediaDeviceLinkTest : public Test
|
||||
{
|
||||
int init()
|
||||
{
|
||||
enumerator = unique_ptr<DeviceEnumerator>(DeviceEnumerator::create());
|
||||
if (!enumerator) {
|
||||
cerr << "Failed to create device enumerator" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (enumerator->enumerate()) {
|
||||
cerr << "Failed to enumerate media devices" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
DeviceMatch dm("vimc");
|
||||
dev_ = enumerator->search(dm);
|
||||
if (!dev_) {
|
||||
cerr << "No VIMC media device found: skip test" << endl;
|
||||
return TestSkip;
|
||||
}
|
||||
|
||||
dev_->acquire();
|
||||
|
||||
if (dev_->open()) {
|
||||
cerr << "Failed to open media device at "
|
||||
<< dev_->devnode() << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
/*
|
||||
* First of all disable all links in the media graph to
|
||||
* ensure we start from a known state.
|
||||
*/
|
||||
if (dev_->disableLinks()) {
|
||||
cerr << "Failed to disable all links in the media graph";
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if link can be consistently retrieved through the
|
||||
* different methods the media device offers.
|
||||
*/
|
||||
string linkName("'Debayer A':[1] -> 'Scaler':[0]'");
|
||||
MediaLink *link = dev_->link("Debayer A", 1, "Scaler", 0);
|
||||
if (!link) {
|
||||
cerr << "Unable to find link: " << linkName
|
||||
<< " using lookup by name" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
MediaEntity *source = dev_->getEntityByName("Debayer A");
|
||||
if (!source) {
|
||||
cerr << "Unable to find entity: 'Debayer A'" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
MediaEntity *sink = dev_->getEntityByName("Scaler");
|
||||
if (!sink) {
|
||||
cerr << "Unable to find entity: 'Scaler'" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
MediaLink *link2 = dev_->link(source, 1, sink, 0);
|
||||
if (!link2) {
|
||||
cerr << "Unable to find link: " << linkName
|
||||
<< " using lookup by entity" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (link != link2) {
|
||||
cerr << "Link lookup by name and by entity don't match"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
link2 = dev_->link(source->getPadByIndex(1),
|
||||
sink->getPadByIndex(0));
|
||||
if (!link2) {
|
||||
cerr << "Unable to find link: " << linkName
|
||||
<< " using lookup by pad" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (link != link2) {
|
||||
cerr << "Link lookup by name and by pad don't match"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* After reset the link shall not be enabled. */
|
||||
if (link->flags() & MEDIA_LNK_FL_ENABLED) {
|
||||
cerr << "Link " << linkName
|
||||
<< " should not be enabled after a device reset"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* Enable the link and test if enabling was successful. */
|
||||
if (link->setEnabled(true)) {
|
||||
cerr << "Failed to enable link: " << linkName
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
|
||||
cerr << "Link " << linkName
|
||||
<< " was enabled but it is reported as disabled"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* Disable the link and test if disabling was successful. */
|
||||
if (link->setEnabled(false)) {
|
||||
cerr << "Failed to disable link: " << linkName
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (link->flags() & MEDIA_LNK_FL_ENABLED) {
|
||||
cerr << "Link " << linkName
|
||||
<< " was disabled but it is reported as enabled"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* Try to get a non existing link. */
|
||||
linkName = "'Sensor A':[1] -> 'Scaler':[0]";
|
||||
link = dev_->link("Sensor A", 1, "Scaler", 0);
|
||||
if (link) {
|
||||
cerr << "Link lookup for " << linkName
|
||||
<< " succeeded but link does not exist"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* Now get an immutable link and try to disable it. */
|
||||
linkName = "'Sensor A':[0] -> 'Raw Capture 0':[0]";
|
||||
link = dev_->link("Sensor A", 0, "Raw Capture 0", 0);
|
||||
if (!link) {
|
||||
cerr << "Unable to find link: " << linkName
|
||||
<< " using lookup by name" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (!(link->flags() & MEDIA_LNK_FL_IMMUTABLE)) {
|
||||
cerr << "Link " << linkName
|
||||
<< " should be 'IMMUTABLE'" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* Disabling an immutable link shall fail. */
|
||||
if (!link->setEnabled(false)) {
|
||||
cerr << "Disabling immutable link " << linkName
|
||||
<< " succeeded but should have failed" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable an disabled link, and verify it is disabled again
|
||||
* after disabling all links in the media graph.
|
||||
*/
|
||||
linkName = "'Debayer B':[1] -> 'Scaler':[0]'";
|
||||
link = dev_->link("Debayer B", 1, "Scaler", 0);
|
||||
if (!link) {
|
||||
cerr << "Unable to find link: " << linkName
|
||||
<< " using lookup by name" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (link->setEnabled(true)) {
|
||||
cerr << "Failed to enable link: " << linkName
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
|
||||
cerr << "Link " << linkName
|
||||
<< " was enabled but it is reported as disabled"
|
||||
<< endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (dev_->disableLinks()) {
|
||||
cerr << "Failed to disable all links in the media graph";
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
if (link->flags() & MEDIA_LNK_FL_ENABLED) {
|
||||
cerr << "All links in the media graph have been disabled"
|
||||
<< " but link " << linkName
|
||||
<< " is still reported as enabled" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
dev_->close();
|
||||
dev_->release();
|
||||
}
|
||||
|
||||
private:
|
||||
unique_ptr<DeviceEnumerator> enumerator;
|
||||
MediaDevice *dev_;
|
||||
};
|
||||
|
||||
TEST_REGISTER(MediaDeviceLinkTest);
|
|
@ -1,5 +1,6 @@
|
|||
media_device_tests = [
|
||||
['media_device_print_test', 'media_device_print_test.cpp'],
|
||||
['media_device_link_test', 'media_device_link_test.cpp'],
|
||||
]
|
||||
|
||||
foreach t : media_device_tests
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue