comparison data/model/test/TestSparseModels.h @ 1713:978c143c767f

Merge from branch single-point
author Chris Cannam
date Fri, 17 May 2019 10:02:43 +0100
parents c077a97d055f
children 417528c41e66
comparison
equal deleted inserted replaced
1709:ab4fd193262b 1713:978c143c767f
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13 */
14
15 #ifndef TEST_SPARSE_MODELS_H
16 #define TEST_SPARSE_MODELS_H
17
18 #include "../SparseOneDimensionalModel.h"
19 #include "../NoteModel.h"
20 #include "../TextModel.h"
21 #include "../PathModel.h"
22 #include "../ImageModel.h"
23
24 #include <QObject>
25 #include <QtTest>
26
27 #include <iostream>
28
29 using namespace std;
30
31 // NB model & dataset IDs in the export tests are incremental,
32 // depending on how many have been exported in previous tests - so
33 // when adding or removing tests we may occasionally need to update
34 // the IDs in other ones
35
36 class TestSparseModels : public QObject
37 {
38 Q_OBJECT
39
40 private slots:
41 void s1d_empty() {
42 SparseOneDimensionalModel m(100, 10, false);
43 QCOMPARE(m.isEmpty(), true);
44 QCOMPARE(m.getEventCount(), 0);
45 QCOMPARE(m.getAllEvents().size(), size_t(0));
46 QCOMPARE(m.getStartFrame(), 0);
47 QCOMPARE(m.getEndFrame(), 0);
48 QCOMPARE(m.getSampleRate(), 100.0);
49 QCOMPARE(m.getResolution(), 10);
50 QCOMPARE(m.isSparse(), true);
51
52 Event p(10);
53 m.add(p);
54 m.remove(p);
55 QCOMPARE(m.isEmpty(), true);
56 QCOMPARE(m.getEventCount(), 0);
57 QCOMPARE(m.getAllEvents().size(), size_t(0));
58 QCOMPARE(m.getStartFrame(), 0);
59 QCOMPARE(m.getEndFrame(), 0);
60 }
61
62 void s1d_extents() {
63 SparseOneDimensionalModel m(100, 10, false);
64 Event p1(20);
65 m.add(p1);
66 QCOMPARE(m.isEmpty(), false);
67 QCOMPARE(m.getEventCount(), 1);
68 Event p2(50);
69 m.add(p2);
70 QCOMPARE(m.isEmpty(), false);
71 QCOMPARE(m.getEventCount(), 2);
72 QCOMPARE(m.getAllEvents().size(), size_t(2));
73 QCOMPARE(*m.getAllEvents().begin(), p1);
74 QCOMPARE(*m.getAllEvents().rbegin(), p2);
75 QCOMPARE(m.getStartFrame(), 20);
76 QCOMPARE(m.getEndFrame(), 60);
77 QCOMPARE(m.containsEvent(p1), true);
78 m.remove(p1);
79 QCOMPARE(m.getEventCount(), 1);
80 QCOMPARE(m.getAllEvents().size(), size_t(1));
81 QCOMPARE(*m.getAllEvents().begin(), p2);
82 QCOMPARE(m.getStartFrame(), 50);
83 QCOMPARE(m.getEndFrame(), 60);
84 QCOMPARE(m.containsEvent(p1), false);
85 }
86
87 void s1d_sample() {
88 SparseOneDimensionalModel m(100, 10, false);
89 Event p1(20), p2(20), p3(50);
90 m.add(p1);
91 m.add(p2);
92 m.add(p3);
93 QCOMPARE(m.getAllEvents().size(), size_t(3));
94 QCOMPARE(*m.getAllEvents().begin(), p1);
95 QCOMPARE(*m.getAllEvents().rbegin(), p3);
96
97 // The EventSeries that is used internally is tested more
98 // thoroughly in its own test suite. This is just a check
99 auto pp = m.getEventsWithin(20, 10);
100 QCOMPARE(pp.size(), size_t(2));
101 QCOMPARE(*pp.begin(), p1);
102 QCOMPARE(*pp.rbegin(), p2);
103
104 pp = m.getEventsWithin(40, 10);
105 QCOMPARE(pp.size(), size_t(0));
106
107 pp = m.getEventsStartingAt(50);
108 QCOMPARE(pp.size(), size_t(1));
109 QCOMPARE(*pp.begin(), p3);
110 }
111
112 void s1d_xml() {
113 SparseOneDimensionalModel m(100, 10, false);
114 m.setObjectName("This \"&\" that");
115 Event p1(20);
116 Event p2(20, "Label &'\">");
117 Event p3(50, 12.4f, 16, ""); // value + duration should not be saved
118 m.add(p1);
119 m.add(p2);
120 m.add(p3);
121 QString xml;
122 QTextStream str(&xml, QIODevice::WriteOnly);
123 m.toXml(str);
124 str.flush();
125 QString expected =
126 "<model id='1' name='This &quot;&amp;&quot; that' sampleRate='100' start='20' end='60' type='sparse' dimensions='1' resolution='10' notifyOnAdd='true' dataset='0' />\n"
127 "<dataset id='0' dimensions='1'>\n"
128 " <point frame='20' label='' />\n"
129 " <point frame='20' label='Label &amp;&apos;&quot;&gt;' />\n"
130 " <point frame='50' label='' />\n"
131 "</dataset>\n";
132 expected.replace("\'", "\"");
133 if (xml != expected) {
134 cerr << "Obtained xml:\n" << xml
135 << "\nExpected:\n" << expected << std::endl;
136 }
137 QCOMPARE(xml, expected);
138 }
139
140 void note_extents() {
141 NoteModel m(100, 10, false);
142 Event p1(20, 123.4f, 40, 0.8f, "note 1");
143 m.add(p1);
144 QCOMPARE(m.isEmpty(), false);
145 QCOMPARE(m.getEventCount(), 1);
146 Event p2(50, 124.3f, 30, 0.9f, "note 2");
147 m.add(p2);
148 QCOMPARE(m.isEmpty(), false);
149 QCOMPARE(m.getEventCount(), 2);
150 QCOMPARE(m.getAllEvents().size(), size_t(2));
151 QCOMPARE(*m.getAllEvents().begin(), p1);
152 QCOMPARE(*m.getAllEvents().rbegin(), p2);
153 QCOMPARE(m.getStartFrame(), 20);
154 QCOMPARE(m.getEndFrame(), 80);
155 QCOMPARE(m.containsEvent(p1), true);
156 QCOMPARE(m.getValueMinimum(), 123.4f);
157 QCOMPARE(m.getValueMaximum(), 124.3f);
158 m.remove(p1);
159 QCOMPARE(m.getEventCount(), 1);
160 QCOMPARE(m.getAllEvents().size(), size_t(1));
161 QCOMPARE(*m.getAllEvents().begin(), p2);
162 QCOMPARE(m.getStartFrame(), 50);
163 QCOMPARE(m.getEndFrame(), 80);
164 QCOMPARE(m.containsEvent(p1), false);
165 }
166
167 void note_sample() {
168 NoteModel m(100, 10, false);
169 Event p1(20, 123.4f, 10, 0.8f, "note 1");
170 Event p2(20, 124.3f, 20, 0.9f, "note 2");
171 Event p3(50, 126.3f, 30, 0.9f, "note 3");
172 m.add(p1);
173 m.add(p2);
174 m.add(p3);
175
176 QCOMPARE(m.getAllEvents().size(), size_t(3));
177 QCOMPARE(*m.getAllEvents().begin(), p1);
178 QCOMPARE(*m.getAllEvents().rbegin(), p3);
179
180 auto pp = m.getEventsSpanning(20, 10);
181 QCOMPARE(pp.size(), size_t(2));
182 QCOMPARE(*pp.begin(), p1);
183 QCOMPARE(*pp.rbegin(), p2);
184
185 pp = m.getEventsSpanning(30, 20);
186 QCOMPARE(pp.size(), size_t(1));
187 QCOMPARE(*pp.begin(), p2);
188
189 pp = m.getEventsSpanning(40, 10);
190 QCOMPARE(pp.size(), size_t(0));
191
192 pp = m.getEventsCovering(50);
193 QCOMPARE(pp.size(), size_t(1));
194 QCOMPARE(*pp.begin(), p3);
195 }
196
197 void note_xml() {
198 NoteModel m(100, 10, false);
199 Event p1(20, 123.4f, 20, 0.8f, "note 1");
200 Event p2(20, 124.3f, 10, 0.9f, "note 2");
201 Event p3(50, 126.3f, 30, 0.9f, "note 3");
202 m.setScaleUnits("Hz");
203 m.add(p1);
204 m.add(p2);
205 m.add(p3);
206 QString xml;
207 QTextStream str(&xml, QIODevice::WriteOnly);
208 m.toXml(str);
209 str.flush();
210
211 QString expected =
212 "<model id='3' name='' sampleRate='100' start='20' end='80' type='sparse' dimensions='3' resolution='10' notifyOnAdd='true' dataset='2' subtype='note' valueQuantization='0' minimum='123.4' maximum='126.3' units='Hz' />\n"
213 "<dataset id='2' dimensions='3'>\n"
214 " <point frame='20' value='124.3' duration='10' level='0.9' label='note 2' />\n"
215 " <point frame='20' value='123.4' duration='20' level='0.8' label='note 1' />\n"
216 " <point frame='50' value='126.3' duration='30' level='0.9' label='note 3' />\n"
217 "</dataset>\n";
218 expected.replace("\'", "\"");
219 if (xml != expected) {
220 cerr << "Obtained xml:\n" << xml
221 << "\nExpected:\n" << expected << std::endl;
222 }
223 QCOMPARE(xml, expected);
224 }
225
226 void text_xml() {
227 TextModel m(100, 10, false);
228 Event p1(20, 1.0f, "text 1");
229 Event p2(20, 0.0f, "text 2");
230 Event p3(50, 0.3f, "text 3");
231 m.add(p1);
232 m.add(p2.withLevel(0.8f));
233 m.add(p3);
234 QString xml;
235 QTextStream str(&xml, QIODevice::WriteOnly);
236 m.toXml(str);
237 str.flush();
238
239 QString expected =
240 "<model id='5' name='' sampleRate='100' start='20' end='60' type='sparse' dimensions='2' resolution='10' notifyOnAdd='true' dataset='4' subtype='text' />\n"
241 "<dataset id='4' dimensions='2'>\n"
242 " <point frame='20' height='0' label='text 2' />\n"
243 " <point frame='20' height='1' label='text 1' />\n"
244 " <point frame='50' height='0.3' label='text 3' />\n"
245 "</dataset>\n";
246 expected.replace("\'", "\"");
247 if (xml != expected) {
248 cerr << "Obtained xml:\n" << xml
249 << "\nExpected:\n" << expected << std::endl;
250 }
251 QCOMPARE(xml, expected);
252 }
253
254 void path_xml() {
255 PathModel m(100, 10, false);
256 PathPoint p1(20, 30);
257 PathPoint p2(40, 60);
258 PathPoint p3(50, 49);
259 m.add(p1);
260 m.add(p2);
261 m.add(p3);
262 QString xml;
263 QTextStream str(&xml, QIODevice::WriteOnly);
264 m.toXml(str);
265 str.flush();
266
267 QString expected =
268 "<model id='6' name='' sampleRate='100' start='20' end='60' type='sparse' dimensions='2' resolution='10' notifyOnAdd='true' dataset='6' subtype='path' />\n"
269 "<dataset id='6' dimensions='2'>\n"
270 " <point frame='20' mapframe='30' />\n"
271 " <point frame='40' mapframe='60' />\n"
272 " <point frame='50' mapframe='49' />\n"
273 "</dataset>\n";
274 expected.replace("\'", "\"");
275 if (xml != expected) {
276 cerr << "Obtained xml:\n" << xml
277 << "\nExpected:\n" << expected << std::endl;
278 }
279 QCOMPARE(xml, expected);
280 }
281
282 void image_xml() {
283 ImageModel m(100, 10, false);
284 Event p1(20, 30, 40, "a label"); // value + duration should not be saved
285 m.add(p1.withURI("/path/to/thing.png").withLevel(0.8f));
286 QString xml;
287 QTextStream str(&xml, QIODevice::WriteOnly);
288 m.toXml(str);
289 str.flush();
290
291 QString expected =
292 "<model id='8' name='' sampleRate='100' start='20' end='30' type='sparse' dimensions='1' resolution='10' notifyOnAdd='true' dataset='7' subtype='image' />\n"
293 "<dataset id='7' dimensions='1'>\n"
294 " <point frame='20' label='a label' image='/path/to/thing.png' />\n"
295 "</dataset>\n";
296 expected.replace("\'", "\"");
297 if (xml != expected) {
298 cerr << "Obtained xml:\n" << xml
299 << "\nExpected:\n" << expected << std::endl;
300 }
301 QCOMPARE(xml, expected);
302 }
303 };
304
305 #endif