Mercurial > hg > vamp-plugin-tester
comparison TestStaticData.cpp @ 0:f89128a316e7
* Commit beginnings of a Vamp plugin test program
author | cannam |
---|---|
date | Thu, 12 Mar 2009 16:23:55 +0000 |
parents | |
children | d8724c5a6d83 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f89128a316e7 |
---|---|
1 /* -*- 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 Copyright 2009 QMUL. | |
8 | |
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 "TestStaticData.h" | |
41 | |
42 #include <vamp-hostsdk/Plugin.h> | |
43 using namespace Vamp; | |
44 | |
45 #include <memory> | |
46 using namespace std; | |
47 | |
48 #include <cmath> | |
49 | |
50 Tester::TestRegistrar<TestIdentifiers> | |
51 TestIdentifiers::m_registrar("Invalid identifiers"); | |
52 | |
53 Tester::TestRegistrar<TestEmptyFields> | |
54 TestEmptyFields::m_registrar("Empty metadata fields"); | |
55 | |
56 Tester::TestRegistrar<TestValueRanges> | |
57 TestValueRanges::m_registrar("Inappropriate value extents"); | |
58 | |
59 Test::Results | |
60 TestIdentifiers::test(string key) | |
61 { | |
62 auto_ptr<Plugin> p(load(key)); | |
63 | |
64 Results r; | |
65 r.push_back(testIdentifier(p->getIdentifier(), "plugin identifier")); | |
66 | |
67 Plugin::ParameterList params = p->getParameterDescriptors(); | |
68 for (int i = 0; i < (int)params.size(); ++i) { | |
69 r.push_back(testIdentifier(params[i].identifier, "parameter identifier")); | |
70 } | |
71 | |
72 Plugin::OutputList outputs = p->getOutputDescriptors(); | |
73 for (int i = 0; i < (int)outputs.size(); ++i) { | |
74 r.push_back(testIdentifier(outputs[i].identifier, "output identifier")); | |
75 } | |
76 | |
77 return r; | |
78 } | |
79 | |
80 Test::Result | |
81 TestIdentifiers::testIdentifier(string identifier, string desc) | |
82 { | |
83 for (int i = 0; i < (int)identifier.length(); ++i) { | |
84 char c = identifier[i]; | |
85 if (c >= 'a' && c <= 'z') continue; | |
86 if (c >= 'A' && c <= 'Z') continue; | |
87 if (c >= '0' && c <= '9') continue; | |
88 if (c == '_' || c == '-') continue; | |
89 return error | |
90 (desc + " \"" + identifier + | |
91 "\" contains invalid character(s); permitted are: [a-zA-Z0-9_-]"); | |
92 } | |
93 return success(); | |
94 } | |
95 | |
96 Test::Results | |
97 TestEmptyFields::test(string key) | |
98 { | |
99 auto_ptr<Plugin> p(load(key)); | |
100 | |
101 Results r; | |
102 | |
103 r.push_back(testMandatory(p->getName(), "plugin name")); | |
104 r.push_back(testRecommended(p->getDescription(), "plugin description")); | |
105 r.push_back(testRecommended(p->getMaker(), "plugin maker")); | |
106 r.push_back(testRecommended(p->getCopyright(), "plugin copyright")); | |
107 | |
108 Plugin::ParameterList params = p->getParameterDescriptors(); | |
109 for (int i = 0; i < (int)params.size(); ++i) { | |
110 r.push_back(testMandatory | |
111 (params[i].name, | |
112 "plugin parameter \"" + params[i].identifier + "\" name")); | |
113 r.push_back(testRecommended | |
114 (params[i].description, | |
115 "plugin parameter \"" + params[i].identifier + "\" description")); | |
116 } | |
117 | |
118 Plugin::OutputList outputs = p->getOutputDescriptors(); | |
119 for (int i = 0; i < (int)outputs.size(); ++i) { | |
120 r.push_back(testMandatory | |
121 (outputs[i].name, | |
122 "plugin output \"" + outputs[i].identifier + "\" name")); | |
123 r.push_back(testRecommended | |
124 (outputs[i].description, | |
125 "plugin output \"" + outputs[i].identifier + "\" description")); | |
126 } | |
127 | |
128 return r; | |
129 } | |
130 | |
131 Test::Result | |
132 TestEmptyFields::testMandatory(string text, string desc) | |
133 { | |
134 if (text == "") { | |
135 return error(desc + " is empty"); | |
136 } | |
137 return success(); | |
138 } | |
139 | |
140 Test::Result | |
141 TestEmptyFields::testRecommended(string text, string desc) | |
142 { | |
143 if (text == "") { | |
144 return warning(desc + " is empty"); | |
145 } | |
146 return success(); | |
147 } | |
148 | |
149 Test::Results | |
150 TestValueRanges::test(string key) | |
151 { | |
152 auto_ptr<Plugin> p(load(key)); | |
153 | |
154 Results r; | |
155 | |
156 Plugin::ParameterList params = p->getParameterDescriptors(); | |
157 for (int i = 0; i < (int)params.size(); ++i) { | |
158 Plugin::ParameterDescriptor &pd(params[i]); | |
159 string pfx("plugin parameter \"" + pd.identifier + "\""); | |
160 float min = pd.minValue; | |
161 float max = pd.maxValue; | |
162 float deft = pd.defaultValue; | |
163 if (max <= min) { | |
164 r.push_back(error(pfx + " maxValue <= minValue")); | |
165 } | |
166 if (deft < min || deft > max) { | |
167 r.push_back(error(pfx + " defaultValue out of range")); | |
168 } | |
169 if (pd.isQuantized) { | |
170 if (pd.quantizeStep == 0.f) { | |
171 r.push_back(error(pfx + " is quantized, but quantize step is zero")); | |
172 } else { | |
173 | |
174 float epsilon = 0.00001f; | |
175 int qty = int((max - min) / pd.quantizeStep + 0.5); | |
176 float target = min + pd.quantizeStep * qty; | |
177 if (fabsf(max - target) > epsilon) { | |
178 r.push_back(warning(pfx + " value range is not a multiple of quantize step")); | |
179 } | |
180 | |
181 if (!pd.valueNames.empty()) { | |
182 if ((int)pd.valueNames.size() < qty+1) { | |
183 r.push_back(warning(pfx + " has fewer value names than quantize steps")); | |
184 } else if ((int)pd.valueNames.size() > qty+1) { | |
185 r.push_back(warning(pfx + " has more value names than quantize steps")); | |
186 } | |
187 } | |
188 | |
189 qty = int((deft - min) / pd.quantizeStep + 0.5); | |
190 target = min + pd.quantizeStep * qty; | |
191 if (fabsf(deft - target) > epsilon) { | |
192 r.push_back(warning(pfx + " default value is not a multiple of quantize step beyond minimum")); | |
193 } | |
194 } | |
195 } | |
196 } | |
197 | |
198 return r; | |
199 } | |
200 | |
201 |