annotate data/model/test/TestSparseModels.h @ 1784:4eac4bf35b45

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