To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / Tester.cpp @ 42:f1e8e14e9c96
History | View | Annotate | Download (7.67 KB)
| 1 | 0:f89128a316e7 | cannam | /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
|---|---|---|---|
| 2 | |||
| 3 | /*
|
||
| 4 | Vamp Plugin Tester
|
||
| 5 | Chris Cannam, cannam@all-day-breakfast.com
|
||
| 6 | Centre for Digital Music, Queen Mary, University of London.
|
||
| 7 | 42:f1e8e14e9c96 | Chris | Copyright 2009-2014 QMUL.
|
| 8 | 0:f89128a316e7 | cannam | |
| 9 | This program loads a Vamp plugin and tests its susceptibility to a
|
||
| 10 | number of common pitfalls, including handling of extremes of input
|
||
| 11 | data. If you can think of any additional useful tests that are
|
||
| 12 | easily added, please send them to me.
|
||
| 13 | |||
| 14 | Permission is hereby granted, free of charge, to any person
|
||
| 15 | obtaining a copy of this software and associated documentation
|
||
| 16 | files (the "Software"), to deal in the Software without
|
||
| 17 | restriction, including without limitation the rights to use, copy,
|
||
| 18 | modify, merge, publish, distribute, sublicense, and/or sell copies
|
||
| 19 | of the Software, and to permit persons to whom the Software is
|
||
| 20 | furnished to do so, subject to the following conditions:
|
||
| 21 | |||
| 22 | The above copyright notice and this permission notice shall be
|
||
| 23 | included in all copies or substantial portions of the Software.
|
||
| 24 | |||
| 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
| 26 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
| 27 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
| 28 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||
| 29 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||
| 30 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
| 31 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
| 32 | |||
| 33 | Except as contained in this notice, the names of the Centre for
|
||
| 34 | Digital Music; Queen Mary, University of London; and Chris Cannam
|
||
| 35 | shall not be used in advertising or otherwise to promote the sale,
|
||
| 36 | use or other dealings in this Software without prior written
|
||
| 37 | authorization.
|
||
| 38 | */
|
||
| 39 | |||
| 40 | #include <vamp-hostsdk/PluginHostAdapter.h> |
||
| 41 | #include <vamp-hostsdk/PluginInputDomainAdapter.h> |
||
| 42 | #include <vamp-hostsdk/PluginLoader.h> |
||
| 43 | |||
| 44 | #include <iostream> |
||
| 45 | |||
| 46 | #include <cstring> |
||
| 47 | #include <cstdlib> |
||
| 48 | #include <cmath> |
||
| 49 | 4:d8724c5a6d83 | cannam | #include <set> |
| 50 | 0:f89128a316e7 | cannam | |
| 51 | #include "Tester.h" |
||
| 52 | |||
| 53 | using Vamp::Plugin;
|
||
| 54 | using Vamp::PluginHostAdapter;
|
||
| 55 | using Vamp::RealTime;
|
||
| 56 | using Vamp::HostExt::PluginLoader;
|
||
| 57 | using Vamp::HostExt::PluginWrapper;
|
||
| 58 | using Vamp::HostExt::PluginInputDomainAdapter;
|
||
| 59 | |||
| 60 | using namespace std; |
||
| 61 | |||
| 62 | 39:07144cdcbedf | Chris | Tester::Tester(std::string key, Test::Options options, std::string singleTestId) : |
| 63 | 8:3019cb6b538d | cannam | m_key(key), |
| 64 | 39:07144cdcbedf | Chris | m_options(options), |
| 65 | m_singleTest(singleTestId) |
||
| 66 | 0:f89128a316e7 | cannam | {
|
| 67 | } |
||
| 68 | |||
| 69 | Tester::~Tester() |
||
| 70 | {
|
||
| 71 | } |
||
| 72 | |||
| 73 | 39:07144cdcbedf | Chris | Tester::NameIndex & |
| 74 | Tester::nameIndex() |
||
| 75 | {
|
||
| 76 | static NameIndex ix;
|
||
| 77 | return ix;
|
||
| 78 | } |
||
| 79 | |||
| 80 | 0:f89128a316e7 | cannam | Tester::Registry & |
| 81 | Tester::registry() |
||
| 82 | {
|
||
| 83 | static Registry r;
|
||
| 84 | return r;
|
||
| 85 | } |
||
| 86 | |||
| 87 | 40:649f32c7eb41 | Chris | void
|
| 88 | Tester::listTests() |
||
| 89 | {
|
||
| 90 | cout << endl; |
||
| 91 | cout << "Total tests: " << nameIndex().size() << "\n" << endl; |
||
| 92 | cout << "ID | Name" << endl;
|
||
| 93 | cout << "---+-----" << endl;
|
||
| 94 | for (NameIndex::const_iterator i = nameIndex().begin();
|
||
| 95 | i != nameIndex().end(); ++i) {
|
||
| 96 | cout << i->first << " | " << i->second << endl;
|
||
| 97 | } |
||
| 98 | cout << endl; |
||
| 99 | } |
||
| 100 | |||
| 101 | 0:f89128a316e7 | cannam | bool
|
| 102 | 4:d8724c5a6d83 | cannam | Tester::test(int ¬es, int &warnings, int &errors) |
| 103 | 0:f89128a316e7 | cannam | {
|
| 104 | /*
|
||
| 105 | |||
| 106 | Things I would like to see tested:
|
||
| 107 | |||
| 108 | * Identifiers for parameters, outputs, or plugin itself contain
|
||
| 109 | illegal characters - DONE
|
||
| 110 | |||
| 111 | * Any of the plugin's name, maker etc fields are empty - DONE
|
||
| 112 | |||
| 113 | 1:d7ef749300ed | cannam | * Default value of a parameter is not quantized as specified - DONE
|
| 114 | |||
| 115 | * Parameter minValue >= maxValue, or defaultValue < minValue
|
||
| 116 | or > maxValue - DONE
|
||
| 117 | |||
| 118 | * Plugin fails when given zero-length or very short input - DONE
|
||
| 119 | |||
| 120 | * Plugin fails when given "all digital zeros" input - DONE
|
||
| 121 | |||
| 122 | * Plugin fails when given input that exceeds +/-1 - DONE
|
||
| 123 | |||
| 124 | * Plugin fails when given "normal" random input (just in case!) - DONE
|
||
| 125 | |||
| 126 | 0:f89128a316e7 | cannam | * Plugin returns different results if another instance is
|
| 127 | 3:0f65bb22172b | cannam | constructed and run "interleaved" with it (from same thread) - DONE
|
| 128 | 0:f89128a316e7 | cannam | |
| 129 | * Plugin's returned timestamps do not change as expected when
|
||
| 130 | run with a different base timestamp for input (though there
|
||
| 131 | 5:6a279da6fdd7 | cannam | could be legitimate reasons for this) - DONE
|
| 132 | 0:f89128a316e7 | cannam | |
| 133 | * Plugin produces different results on second run, after reset
|
||
| 134 | 3:0f65bb22172b | cannam | called - DONE
|
| 135 | 0:f89128a316e7 | cannam | |
| 136 | * Initial value of a parameter on plugin construction differs
|
||
| 137 | from its default value (i.e. plugin produces different
|
||
| 138 | results depending on whether parameter is set explicitly by
|
||
| 139 | 6:ba3c8cc649d3 | cannam | host to default value or not) - DONE
|
| 140 | 0:f89128a316e7 | cannam | |
| 141 | * If a plugin reports any programs, selecting default program
|
||
| 142 | 6:ba3c8cc649d3 | cannam | explicitly changes results (as for default parameters) - DONE
|
| 143 | 0:f89128a316e7 | cannam | |
| 144 | * Output feature does not hasTimestamp when output type is
|
||
| 145 | 5:6a279da6fdd7 | cannam | VariableSampleRate - DONE
|
| 146 | 0:f89128a316e7 | cannam | |
| 147 | * Output feature hasTimestamp or hasDuration when output type is
|
||
| 148 | 5:6a279da6fdd7 | cannam | OneSamplePerStep (warning only, this is not an error) - DONE
|
| 149 | 0:f89128a316e7 | cannam | |
| 150 | * Plugin returns features whose output numbers do not have
|
||
| 151 | 5:6a279da6fdd7 | cannam | a corresponding record in output descriptor list - DONE
|
| 152 | 0:f89128a316e7 | cannam | |
| 153 | * Plugin fails to return any features on some output (warning
|
||
| 154 | 5:6a279da6fdd7 | cannam | only) - DONE
|
| 155 | 0:f89128a316e7 | cannam | |
| 156 | * Constructor takes a long time to run. A fuzzy concept, but
|
||
| 157 | suggests that some work should have been deferred to
|
||
| 158 | 6:ba3c8cc649d3 | cannam | initialise(). Warning only - DONE
|
| 159 | |||
| 160 | * Plugin fails gracelessly when constructed with "weird" sample
|
||
| 161 | rate or initialised with "wrong" step size, block size, or
|
||
| 162 | number of channels
|
||
| 163 | 0:f89128a316e7 | cannam | |
| 164 | Well, that's quite a lot of tests already. What else?
|
||
| 165 | |||
| 166 | */
|
||
| 167 | |||
| 168 | bool good = true; |
||
| 169 | |||
| 170 | try {
|
||
| 171 | |||
| 172 | 39:07144cdcbedf | Chris | if (m_options & Test::SingleTest) {
|
| 173 | 4:d8724c5a6d83 | cannam | |
| 174 | 39:07144cdcbedf | Chris | if (registry().find(m_singleTest) != registry().end()) {
|
| 175 | |||
| 176 | good = performTest(m_singleTest, notes, warnings, errors); |
||
| 177 | |||
| 178 | } else {
|
||
| 179 | |||
| 180 | std::cout << " ** ERROR: Unknown single-test id \""
|
||
| 181 | << m_singleTest << "\"" << std::endl;
|
||
| 182 | good = false;
|
||
| 183 | } |
||
| 184 | |||
| 185 | } else {
|
||
| 186 | |||
| 187 | for (Registry::const_iterator i = registry().begin();
|
||
| 188 | i != registry().end(); ++i) {
|
||
| 189 | |||
| 190 | bool thisGood = performTest(i->first, notes, warnings, errors);
|
||
| 191 | if (!thisGood) good = false; |
||
| 192 | 0:f89128a316e7 | cannam | } |
| 193 | } |
||
| 194 | 39:07144cdcbedf | Chris | |
| 195 | 0:f89128a316e7 | cannam | } catch (Test::FailedToLoadPlugin) {
|
| 196 | 17:ea8865f488a0 | cannam | std::cout << " ** ERROR: Failed to load plugin (key = \"" << m_key
|
| 197 | 0:f89128a316e7 | cannam | << "\")" << std::endl;
|
| 198 | 25:612333efd521 | cannam | std::cout << " ** NOTE: Vamp plugin path is: " << std::endl;
|
| 199 | std::vector<std::string> pp = PluginHostAdapter::getPluginPath();
|
||
| 200 | for (size_t i = 0; i < pp.size(); ++i) { |
||
| 201 | std::cout << " " << pp[i] << std::endl;
|
||
| 202 | } |
||
| 203 | 26:eff1772ba397 | cannam | good = false;
|
| 204 | 0:f89128a316e7 | cannam | } |
| 205 | |||
| 206 | return good;
|
||
| 207 | } |
||
| 208 | |||
| 209 | 39:07144cdcbedf | Chris | bool
|
| 210 | Tester::performTest(std::string id, int ¬es, int &warnings, int &errors) |
||
| 211 | {
|
||
| 212 | std::cout << " -- Performing test: "
|
||
| 213 | << id |
||
| 214 | << " "
|
||
| 215 | << nameIndex()[id] |
||
| 216 | << std::endl; |
||
| 217 | |||
| 218 | Test *test = registry()[id]->makeTest(); |
||
| 219 | Test::Results results = test->test(m_key, m_options); |
||
| 220 | delete test;
|
||
| 221 | |||
| 222 | set<string> printed;
|
||
| 223 | |||
| 224 | bool good = true; |
||
| 225 | |||
| 226 | for (int j = 0; j < (int)results.size(); ++j) { |
||
| 227 | string message = results[j].message();
|
||
| 228 | if (printed.find(message) != printed.end()) continue; |
||
| 229 | printed.insert(message); |
||
| 230 | switch (results[j].code()) {
|
||
| 231 | case Test::Result::Success:
|
||
| 232 | break;
|
||
| 233 | case Test::Result::Note:
|
||
| 234 | std::cout << " ** NOTE: " << results[j].message() << std::endl;
|
||
| 235 | ++notes; |
||
| 236 | break;
|
||
| 237 | case Test::Result::Warning:
|
||
| 238 | std::cout << " ** WARNING: " << results[j].message() << std::endl;
|
||
| 239 | ++warnings; |
||
| 240 | break;
|
||
| 241 | case Test::Result::Error:
|
||
| 242 | std::cout << " ** ERROR: " << results[j].message() << std::endl;
|
||
| 243 | ++errors; |
||
| 244 | good = false;
|
||
| 245 | break;
|
||
| 246 | } |
||
| 247 | } |
||
| 248 | |||
| 249 | return good;
|
||
| 250 | } |