annotate TestStaticData.cpp @ 26:eff1772ba397 vamp-plugin-tester-v1.0-erroneous

* More doc corrections to match error reporting updates in SDK * Don't return success after failing to load a plugin!
author cannam
date Tue, 22 Sep 2009 11:24:31 +0000
parents ea8865f488a0
children b700f37dc118
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 Vamp Plugin Tester
cannam@0 5 Chris Cannam, cannam@all-day-breakfast.com
cannam@0 6 Centre for Digital Music, Queen Mary, University of London.
cannam@0 7 Copyright 2009 QMUL.
cannam@0 8
cannam@0 9 This program loads a Vamp plugin and tests its susceptibility to a
cannam@0 10 number of common pitfalls, including handling of extremes of input
cannam@0 11 data. If you can think of any additional useful tests that are
cannam@0 12 easily added, please send them to me.
cannam@0 13
cannam@0 14 Permission is hereby granted, free of charge, to any person
cannam@0 15 obtaining a copy of this software and associated documentation
cannam@0 16 files (the "Software"), to deal in the Software without
cannam@0 17 restriction, including without limitation the rights to use, copy,
cannam@0 18 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@0 19 of the Software, and to permit persons to whom the Software is
cannam@0 20 furnished to do so, subject to the following conditions:
cannam@0 21
cannam@0 22 The above copyright notice and this permission notice shall be
cannam@0 23 included in all copies or substantial portions of the Software.
cannam@0 24
cannam@0 25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@0 26 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@0 27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@0 28 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@0 29 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@0 30 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@0 31 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@0 32
cannam@0 33 Except as contained in this notice, the names of the Centre for
cannam@0 34 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@0 35 shall not be used in advertising or otherwise to promote the sale,
cannam@0 36 use or other dealings in this Software without prior written
cannam@0 37 authorization.
cannam@0 38 */
cannam@0 39
cannam@0 40 #include "TestStaticData.h"
cannam@0 41
cannam@0 42 #include <vamp-hostsdk/Plugin.h>
cannam@0 43 using namespace Vamp;
cannam@0 44
cannam@0 45 #include <memory>
cannam@0 46 using namespace std;
cannam@0 47
cannam@0 48 #include <cmath>
cannam@0 49
cannam@0 50 Tester::TestRegistrar<TestIdentifiers>
cannam@4 51 TestIdentifiers::m_registrar("A1 Invalid identifiers");
cannam@0 52
cannam@0 53 Tester::TestRegistrar<TestEmptyFields>
cannam@4 54 TestEmptyFields::m_registrar("A2 Empty metadata fields");
cannam@0 55
cannam@0 56 Tester::TestRegistrar<TestValueRanges>
cannam@4 57 TestValueRanges::m_registrar("A3 Inappropriate value extents");
cannam@0 58
cannam@0 59 Test::Results
cannam@14 60 TestIdentifiers::test(string key, Options)
cannam@0 61 {
cannam@0 62 auto_ptr<Plugin> p(load(key));
cannam@0 63
cannam@0 64 Results r;
cannam@17 65 r.push_back(testIdentifier(p->getIdentifier(), "Plugin identifier"));
cannam@0 66
cannam@0 67 Plugin::ParameterList params = p->getParameterDescriptors();
cannam@0 68 for (int i = 0; i < (int)params.size(); ++i) {
cannam@17 69 r.push_back(testIdentifier(params[i].identifier, "Parameter identifier"));
cannam@0 70 }
cannam@0 71
cannam@0 72 Plugin::OutputList outputs = p->getOutputDescriptors();
cannam@0 73 for (int i = 0; i < (int)outputs.size(); ++i) {
cannam@17 74 r.push_back(testIdentifier(outputs[i].identifier, "Output identifier"));
cannam@0 75 }
cannam@0 76
cannam@0 77 return r;
cannam@0 78 }
cannam@0 79
cannam@0 80 Test::Result
cannam@0 81 TestIdentifiers::testIdentifier(string identifier, string desc)
cannam@0 82 {
cannam@0 83 for (int i = 0; i < (int)identifier.length(); ++i) {
cannam@0 84 char c = identifier[i];
cannam@0 85 if (c >= 'a' && c <= 'z') continue;
cannam@0 86 if (c >= 'A' && c <= 'Z') continue;
cannam@0 87 if (c >= '0' && c <= '9') continue;
cannam@0 88 if (c == '_' || c == '-') continue;
cannam@0 89 return error
cannam@0 90 (desc + " \"" + identifier +
cannam@0 91 "\" contains invalid character(s); permitted are: [a-zA-Z0-9_-]");
cannam@0 92 }
cannam@0 93 return success();
cannam@0 94 }
cannam@0 95
cannam@0 96 Test::Results
cannam@14 97 TestEmptyFields::test(string key, Options)
cannam@0 98 {
cannam@0 99 auto_ptr<Plugin> p(load(key));
cannam@0 100
cannam@0 101 Results r;
cannam@0 102
cannam@17 103 r.push_back(testMandatory(p->getName(), "Plugin name"));
cannam@17 104 r.push_back(testRecommended(p->getDescription(), "Plugin description"));
cannam@17 105 r.push_back(testRecommended(p->getMaker(), "Plugin maker"));
cannam@17 106 r.push_back(testRecommended(p->getCopyright(), "Plugin copyright"));
cannam@0 107
cannam@0 108 Plugin::ParameterList params = p->getParameterDescriptors();
cannam@0 109 for (int i = 0; i < (int)params.size(); ++i) {
cannam@0 110 r.push_back(testMandatory
cannam@0 111 (params[i].name,
cannam@17 112 "Plugin parameter \"" + params[i].identifier + "\" name"));
cannam@0 113 r.push_back(testRecommended
cannam@0 114 (params[i].description,
cannam@17 115 "Plugin parameter \"" + params[i].identifier + "\" description"));
cannam@0 116 }
cannam@0 117
cannam@0 118 Plugin::OutputList outputs = p->getOutputDescriptors();
cannam@0 119 for (int i = 0; i < (int)outputs.size(); ++i) {
cannam@0 120 r.push_back(testMandatory
cannam@0 121 (outputs[i].name,
cannam@17 122 "Plugin output \"" + outputs[i].identifier + "\" name"));
cannam@0 123 r.push_back(testRecommended
cannam@0 124 (outputs[i].description,
cannam@17 125 "Plugin output \"" + outputs[i].identifier + "\" description"));
cannam@0 126 }
cannam@0 127
cannam@0 128 return r;
cannam@0 129 }
cannam@0 130
cannam@0 131 Test::Result
cannam@0 132 TestEmptyFields::testMandatory(string text, string desc)
cannam@0 133 {
cannam@0 134 if (text == "") {
cannam@0 135 return error(desc + " is empty");
cannam@0 136 }
cannam@0 137 return success();
cannam@0 138 }
cannam@0 139
cannam@0 140 Test::Result
cannam@0 141 TestEmptyFields::testRecommended(string text, string desc)
cannam@0 142 {
cannam@0 143 if (text == "") {
cannam@0 144 return warning(desc + " is empty");
cannam@0 145 }
cannam@0 146 return success();
cannam@0 147 }
cannam@0 148
cannam@0 149 Test::Results
cannam@14 150 TestValueRanges::test(string key, Options)
cannam@0 151 {
cannam@0 152 auto_ptr<Plugin> p(load(key));
cannam@0 153
cannam@0 154 Results r;
cannam@0 155
cannam@0 156 Plugin::ParameterList params = p->getParameterDescriptors();
cannam@0 157 for (int i = 0; i < (int)params.size(); ++i) {
cannam@0 158 Plugin::ParameterDescriptor &pd(params[i]);
cannam@17 159 string pfx("Plugin parameter \"" + pd.identifier + "\"");
cannam@0 160 float min = pd.minValue;
cannam@0 161 float max = pd.maxValue;
cannam@0 162 float deft = pd.defaultValue;
cannam@0 163 if (max <= min) {
cannam@0 164 r.push_back(error(pfx + " maxValue <= minValue"));
cannam@0 165 }
cannam@0 166 if (deft < min || deft > max) {
cannam@0 167 r.push_back(error(pfx + " defaultValue out of range"));
cannam@0 168 }
cannam@0 169 if (pd.isQuantized) {
cannam@0 170 if (pd.quantizeStep == 0.f) {
cannam@0 171 r.push_back(error(pfx + " is quantized, but quantize step is zero"));
cannam@0 172 } else {
cannam@0 173
cannam@0 174 float epsilon = 0.00001f;
cannam@0 175 int qty = int((max - min) / pd.quantizeStep + 0.5);
cannam@0 176 float target = min + pd.quantizeStep * qty;
cannam@0 177 if (fabsf(max - target) > epsilon) {
cannam@0 178 r.push_back(warning(pfx + " value range is not a multiple of quantize step"));
cannam@0 179 }
cannam@0 180
cannam@0 181 if (!pd.valueNames.empty()) {
cannam@0 182 if ((int)pd.valueNames.size() < qty+1) {
cannam@0 183 r.push_back(warning(pfx + " has fewer value names than quantize steps"));
cannam@0 184 } else if ((int)pd.valueNames.size() > qty+1) {
cannam@0 185 r.push_back(warning(pfx + " has more value names than quantize steps"));
cannam@0 186 }
cannam@0 187 }
cannam@0 188
cannam@0 189 qty = int((deft - min) / pd.quantizeStep + 0.5);
cannam@0 190 target = min + pd.quantizeStep * qty;
cannam@0 191 if (fabsf(deft - target) > epsilon) {
cannam@0 192 r.push_back(warning(pfx + " default value is not a multiple of quantize step beyond minimum"));
cannam@0 193 }
cannam@0 194 }
cannam@0 195 }
cannam@0 196 }
cannam@0 197
cannam@0 198 return r;
cannam@0 199 }
cannam@0 200
cannam@0 201