Mercurial > hg > svcore
comparison data/fileio/test/CSVStreamWriterTest.h @ 1527:710e6250a401 zoom
Merge from default branch
| author | Chris Cannam |
|---|---|
| date | Mon, 17 Sep 2018 13:51:14 +0100 |
| parents | 0d4f1fcad97a |
| children | 560453546749 |
comparison
equal
deleted
inserted
replaced
| 1324:d4a28d1479a8 | 1527:710e6250a401 |
|---|---|
| 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 This file copyright 2017 Queen Mary, University of London. | |
| 8 | |
| 9 This program is free software; you can redistribute it and/or | |
| 10 modify it under the terms of the GNU General Public License as | |
| 11 published by the Free Software Foundation; either version 2 of the | |
| 12 License, or (at your option) any later version. See the file | |
| 13 COPYING included with this distribution for more information. | |
| 14 */ | |
| 15 | |
| 16 #ifndef TEST_CSV_STREAM_H | |
| 17 #define TEST_CSV_STREAM_H | |
| 18 | |
| 19 #include <QtTest> | |
| 20 #include <QObject> | |
| 21 #include <sstream> | |
| 22 #include <functional> | |
| 23 | |
| 24 #include "base/ProgressReporter.h" | |
| 25 #include "base/DataExportOptions.h" | |
| 26 #include "base/Selection.h" | |
| 27 #include "data/model/NoteModel.h" | |
| 28 #include "../CSVStreamWriter.h" | |
| 29 #include "../../model/test/MockWaveModel.h" | |
| 30 | |
| 31 class StubReporter : public ProgressReporter | |
| 32 { | |
| 33 public: | |
| 34 StubReporter( std::function<bool()> isCancelled ) | |
| 35 : m_isCancelled(isCancelled) {} | |
| 36 bool isDefinite() const override { return true; } | |
| 37 void setDefinite(bool) override {} | |
| 38 bool wasCancelled() const override { return m_isCancelled(); } | |
| 39 void setMessage(QString) override {} | |
| 40 void setProgress(int p) override | |
| 41 { | |
| 42 ++m_calls; | |
| 43 m_percentageLog.push_back(p); | |
| 44 } | |
| 45 | |
| 46 size_t getCallCount() const { return m_calls; } | |
| 47 std::vector<int> getPercentageLog() const { return m_percentageLog; } | |
| 48 void reset() { m_calls = 0; } | |
| 49 private: | |
| 50 size_t m_calls = 0; | |
| 51 std::function<bool()> m_isCancelled; | |
| 52 std::vector<int> m_percentageLog; | |
| 53 }; | |
| 54 | |
| 55 class CSVStreamWriterTest : public QObject | |
| 56 { | |
| 57 Q_OBJECT | |
| 58 public: | |
| 59 std::string getExpectedString() | |
| 60 { | |
| 61 return | |
| 62 { | |
| 63 "0,0,0\n" | |
| 64 "1,0,0\n" | |
| 65 "2,0,0\n" | |
| 66 "3,0,0\n" | |
| 67 "4,1,1\n" | |
| 68 "5,1,1\n" | |
| 69 "6,1,1\n" | |
| 70 "7,1,1\n" | |
| 71 "8,1,1\n" | |
| 72 "9,1,1\n" | |
| 73 "10,1,1\n" | |
| 74 "11,1,1\n" | |
| 75 "12,1,1\n" | |
| 76 "13,1,1\n" | |
| 77 "14,1,1\n" | |
| 78 "15,1,1\n" | |
| 79 "16,1,1\n" | |
| 80 "17,1,1\n" | |
| 81 "18,1,1\n" | |
| 82 "19,1,1\n" | |
| 83 "20,0,0\n" | |
| 84 "21,0,0\n" | |
| 85 "22,0,0\n" | |
| 86 "23,0,0" | |
| 87 }; | |
| 88 } | |
| 89 | |
| 90 private slots: | |
| 91 void simpleValidOutput() | |
| 92 { | |
| 93 MockWaveModel mwm({ DC, DC }, 16, 4); | |
| 94 | |
| 95 std::ostringstream oss; | |
| 96 const auto result = CSVStreamWriter::writeInChunks(oss, mwm); | |
| 97 QVERIFY( oss.str() == getExpectedString() ); | |
| 98 QVERIFY( result ); | |
| 99 } | |
| 100 | |
| 101 void callsReporterCorrectTimes() | |
| 102 { | |
| 103 MockWaveModel mwm({ DC, DC }, 16, 4); | |
| 104 StubReporter reporter { []() -> bool { return false; } }; | |
| 105 const auto expected = getExpectedString(); | |
| 106 | |
| 107 std::ostringstream oss; | |
| 108 const auto writeStreamWithBlockSize = [&](int blockSize) { | |
| 109 return CSVStreamWriter::writeInChunks( | |
| 110 oss, | |
| 111 mwm, | |
| 112 &reporter, | |
| 113 ",", | |
| 114 DataExportDefaults, | |
| 115 blockSize | |
| 116 ); | |
| 117 }; | |
| 118 | |
| 119 const auto reset = [&]() { | |
| 120 oss.str({}); | |
| 121 reporter.reset(); | |
| 122 }; | |
| 123 | |
| 124 const auto nonIntegerMultipleResult = writeStreamWithBlockSize(5); | |
| 125 QVERIFY( nonIntegerMultipleResult ); | |
| 126 QVERIFY( reporter.getCallCount() == 5 /* 4.8 rounded up */ ); | |
| 127 QVERIFY( oss.str() == expected ); | |
| 128 reset(); | |
| 129 | |
| 130 const auto integerMultiple = writeStreamWithBlockSize(2); | |
| 131 QVERIFY( integerMultiple ); | |
| 132 QVERIFY( reporter.getCallCount() == 12 ); | |
| 133 QVERIFY( oss.str() == expected ); | |
| 134 reset(); | |
| 135 | |
| 136 const auto largerThanNumberOfSamples = writeStreamWithBlockSize(100); | |
| 137 QVERIFY( largerThanNumberOfSamples ); | |
| 138 QVERIFY( reporter.getCallCount() == 1 ); | |
| 139 QVERIFY( oss.str() == expected ); | |
| 140 reset(); | |
| 141 | |
| 142 const auto zero = writeStreamWithBlockSize(0); | |
| 143 QVERIFY( zero == false ); | |
| 144 QVERIFY( reporter.getCallCount() == 0 ); | |
| 145 } | |
| 146 | |
| 147 void isCancellable() | |
| 148 { | |
| 149 MockWaveModel mwm({ DC, DC }, 16, 4); | |
| 150 StubReporter reporter { []() -> bool { return true; } }; | |
| 151 | |
| 152 std::ostringstream oss; | |
| 153 const auto cancelImmediately = CSVStreamWriter::writeInChunks( | |
| 154 oss, | |
| 155 mwm, | |
| 156 &reporter, | |
| 157 ",", | |
| 158 DataExportDefaults, | |
| 159 4 | |
| 160 ); | |
| 161 QVERIFY( cancelImmediately == false ); | |
| 162 QVERIFY( reporter.getCallCount() == 0 ); | |
| 163 | |
| 164 StubReporter cancelMidway { | |
| 165 [&]() { return cancelMidway.getCallCount() == 3; } | |
| 166 }; | |
| 167 const auto cancelledMidway = CSVStreamWriter::writeInChunks( | |
| 168 oss, | |
| 169 mwm, | |
| 170 &cancelMidway, | |
| 171 ",", | |
| 172 DataExportDefaults, | |
| 173 4 | |
| 174 ); | |
| 175 QVERIFY( cancelMidway.getCallCount() == 3 ); | |
| 176 QVERIFY( cancelledMidway == false ); | |
| 177 } | |
| 178 | |
| 179 void zeroStartTimeReportsPercentageCorrectly() | |
| 180 { | |
| 181 MockWaveModel mwm({ DC, DC }, 16, 4); | |
| 182 StubReporter reporter { []() -> bool { return false; } }; | |
| 183 std::ostringstream oss; | |
| 184 const auto succeeded = CSVStreamWriter::writeInChunks( | |
| 185 oss, | |
| 186 mwm, | |
| 187 &reporter, | |
| 188 ",", | |
| 189 DataExportDefaults, | |
| 190 4 | |
| 191 ); | |
| 192 QVERIFY( succeeded == true ); | |
| 193 QVERIFY( reporter.getCallCount() == 6 ); | |
| 194 const std::vector<int> expectedCallLog { | |
| 195 16, | |
| 196 33, | |
| 197 50, | |
| 198 66, | |
| 199 83, | |
| 200 100 | |
| 201 }; | |
| 202 QVERIFY( reporter.getPercentageLog() == expectedCallLog ); | |
| 203 QVERIFY( oss.str() == getExpectedString() ); | |
| 204 } | |
| 205 | |
| 206 void nonZeroStartTimeReportsPercentageCorrectly() | |
| 207 { | |
| 208 MockWaveModel mwm({ DC, DC }, 16, 4); | |
| 209 StubReporter reporter { []() -> bool { return false; } }; | |
| 210 std::ostringstream oss; | |
| 211 const auto writeSubSection = CSVStreamWriter::writeInChunks( | |
| 212 oss, | |
| 213 mwm, | |
| 214 {4, 20}, | |
| 215 &reporter, | |
| 216 ",", | |
| 217 DataExportDefaults, | |
| 218 4 | |
| 219 ); | |
| 220 QVERIFY( reporter.getCallCount() == 4 ); | |
| 221 const std::vector<int> expectedCallLog { | |
| 222 25, | |
| 223 50, | |
| 224 75, | |
| 225 100 | |
| 226 }; | |
| 227 QVERIFY( reporter.getPercentageLog() == expectedCallLog ); | |
| 228 QVERIFY( writeSubSection == true ); | |
| 229 const std::string expectedOutput { | |
| 230 "4,1,1\n" | |
| 231 "5,1,1\n" | |
| 232 "6,1,1\n" | |
| 233 "7,1,1\n" | |
| 234 "8,1,1\n" | |
| 235 "9,1,1\n" | |
| 236 "10,1,1\n" | |
| 237 "11,1,1\n" | |
| 238 "12,1,1\n" | |
| 239 "13,1,1\n" | |
| 240 "14,1,1\n" | |
| 241 "15,1,1\n" | |
| 242 "16,1,1\n" | |
| 243 "17,1,1\n" | |
| 244 "18,1,1\n" | |
| 245 "19,1,1" | |
| 246 }; | |
| 247 QVERIFY( oss.str() == expectedOutput ); | |
| 248 } | |
| 249 | |
| 250 void multipleSelectionOutput() | |
| 251 { | |
| 252 MockWaveModel mwm({ DC, DC }, 16, 4); | |
| 253 StubReporter reporter { []() -> bool { return false; } }; | |
| 254 std::ostringstream oss; | |
| 255 MultiSelection regions; | |
| 256 regions.addSelection({0, 2}); | |
| 257 regions.addSelection({4, 6}); | |
| 258 regions.addSelection({16, 18}); | |
| 259 // qDebug("End frame: %lld", (long long int)mwm.getEndFrame()); | |
| 260 const std::string expectedOutput { | |
| 261 "0,0,0\n" | |
| 262 "1,0,0\n" | |
| 263 "4,1,1\n" | |
| 264 "5,1,1\n" | |
| 265 "16,1,1\n" | |
| 266 "17,1,1" | |
| 267 }; | |
| 268 const auto wroteMultiSection = CSVStreamWriter::writeInChunks( | |
| 269 oss, | |
| 270 mwm, | |
| 271 regions, | |
| 272 &reporter, | |
| 273 ",", | |
| 274 DataExportDefaults, | |
| 275 2 | |
| 276 ); | |
| 277 QVERIFY( wroteMultiSection == true ); | |
| 278 QVERIFY( reporter.getCallCount() == 3 ); | |
| 279 const std::vector<int> expectedCallLog { 33, 66, 100 }; | |
| 280 QVERIFY( reporter.getPercentageLog() == expectedCallLog ); | |
| 281 // qDebug("%s", oss.str().c_str()); | |
| 282 QVERIFY( oss.str() == expectedOutput ); | |
| 283 } | |
| 284 | |
| 285 void writeSparseModel() | |
| 286 { | |
| 287 const auto pentatonicFromRoot = [](float midiPitch) { | |
| 288 return std::vector<float> { | |
| 289 0 + midiPitch, | |
| 290 2 + midiPitch, | |
| 291 4 + midiPitch, | |
| 292 7 + midiPitch, | |
| 293 9 + midiPitch | |
| 294 }; | |
| 295 }; | |
| 296 const auto cMajorPentatonic = pentatonicFromRoot(60.0); | |
| 297 NoteModel notes(8 /* sampleRate */, 4 /* resolution */); | |
| 298 sv_frame_t startFrame = 0; | |
| 299 for (const auto& note : cMajorPentatonic) { | |
| 300 notes.addPoint({startFrame, note, 4, 1.f, ""}); | |
| 301 startFrame += 8; | |
| 302 } | |
| 303 // qDebug("Create Expected Output\n"); | |
| 304 | |
| 305 // NB. removed end line break | |
| 306 const auto expectedOutput = notes.toDelimitedDataString(",").trimmed(); | |
| 307 | |
| 308 StubReporter reporter { []() -> bool { return false; } }; | |
| 309 std::ostringstream oss; | |
| 310 // qDebug("End frame: %lld", (long long int)notes.getEndFrame()); | |
| 311 // qDebug("Write streaming\n"); | |
| 312 const auto wroteSparseModel = CSVStreamWriter::writeInChunks( | |
| 313 oss, | |
| 314 notes, | |
| 315 &reporter, | |
| 316 ",", | |
| 317 DataExportDefaults, | |
| 318 2 | |
| 319 ); | |
| 320 | |
| 321 // qDebug("\n%s\n", expectedOutput.toLocal8Bit().data()); | |
| 322 // qDebug("\n%s\n", oss.str().c_str()); | |
| 323 QVERIFY( wroteSparseModel == true ); | |
| 324 QVERIFY( oss.str() == expectedOutput.toStdString() ); | |
| 325 } | |
| 326 }; | |
| 327 | |
| 328 #endif |
