From d833c1d39e75141f98ab88f9952f9b86a4243006 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 11 Jan 2019 10:18:56 +0100 Subject: test: media_device: Add link handling test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test unit that exercise link handling on the VIMC media graph. Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- test/media_device/media_device_link_test.cpp | 246 +++++++++++++++++++++++++++ test/media_device/meson.build | 1 + 2 files changed, 247 insertions(+) create mode 100644 test/media_device/media_device_link_test.cpp diff --git a/test/media_device/media_device_link_test.cpp b/test/media_device/media_device_link_test.cpp new file mode 100644 index 00000000..2297e335 --- /dev/null +++ b/test/media_device/media_device_link_test.cpp @@ -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 +#include + +#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::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 enumerator; + MediaDevice *dev_; +}; + +TEST_REGISTER(MediaDeviceLinkTest); diff --git a/test/media_device/meson.build b/test/media_device/meson.build index e4bedb79..d91a022f 100644 --- a/test/media_device/meson.build +++ b/test/media_device/meson.build @@ -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 -- cgit v1.2.1