annotate data/fileio/test/CSVFormatTest.h @ 1854:bde22957545e

Add support for doubling escapes for quotes in quoted texts in CSV-like formats on import (similar to how we, and the relevant RFC, do escaping on export now)
author Chris Cannam
date Mon, 11 May 2020 14:43:58 +0100
parents 9570ef94eaa3
children 1b8c4ee06f6d
rev   line source
Chris@1345 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1345 2
Chris@1345 3 /*
Chris@1345 4 Sonic Visualiser
Chris@1345 5 An audio file viewer and annotation editor.
Chris@1345 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1345 7
Chris@1345 8 This program is free software; you can redistribute it and/or
Chris@1345 9 modify it under the terms of the GNU General Public License as
Chris@1345 10 published by the Free Software Foundation; either version 2 of the
Chris@1345 11 License, or (at your option) any later version. See the file
Chris@1345 12 COPYING included with this distribution for more information.
Chris@1345 13 */
Chris@1345 14
Chris@1524 15 #ifndef TEST_CSV_FORMAT_H
Chris@1524 16 #define TEST_CSV_FORMAT_H
Chris@1345 17
Chris@1524 18 // Tests for the code that guesses the most likely format for parsing a CSV file
Chris@1345 19
Chris@1524 20 #include "../CSVFormat.h"
Chris@1524 21
Chris@1524 22 #include "base/Debug.h"
Chris@1345 23
Chris@1345 24 #include <cmath>
Chris@1345 25
Chris@1345 26 #include <QObject>
Chris@1345 27 #include <QtTest>
Chris@1345 28 #include <QDir>
Chris@1345 29
Chris@1345 30 #include <iostream>
Chris@1345 31
Chris@1345 32 using namespace std;
Chris@1345 33
Chris@1524 34 class CSVFormatTest : public QObject
Chris@1345 35 {
Chris@1345 36 Q_OBJECT
Chris@1345 37
Chris@1346 38 private:
Chris@1524 39 QDir csvDir;
Chris@1346 40
Chris@1346 41 public:
Chris@1524 42 CSVFormatTest(QString base) {
Chris@1346 43 if (base == "") {
Chris@1346 44 base = "svcore/data/fileio/test";
Chris@1346 45 }
Chris@1524 46 csvDir = QDir(base + "/csv");
Chris@1346 47 }
Chris@1346 48
Chris@1524 49 private slots:
Chris@1524 50 void init() {
Chris@1524 51 if (!csvDir.exists()) {
Chris@1524 52 SVCERR << "ERROR: CSV test file directory \"" << csvDir.absolutePath() << "\" does not exist" << endl;
Chris@1524 53 QVERIFY2(csvDir.exists(), "CSV test file directory not found");
Chris@1359 54 }
Chris@1359 55 }
Chris@1359 56
Chris@1524 57 void separatorComma() {
Chris@1524 58 CSVFormat f;
Chris@1524 59 QVERIFY(f.guessFormatFor(csvDir.filePath("separator-comma.csv")));
Chris@1524 60 QCOMPARE(f.getSeparator(), QChar(','));
Chris@1524 61 QCOMPARE(f.getColumnCount(), 3);
Chris@1524 62 }
Chris@1524 63
Chris@1524 64 void separatorTab() {
Chris@1524 65 CSVFormat f;
Chris@1524 66 QVERIFY(f.guessFormatFor(csvDir.filePath("separator-tab.csv")));
Chris@1524 67 QCOMPARE(f.getSeparator(), QChar('\t'));
Chris@1524 68 QCOMPARE(f.getColumnCount(), 3);
Chris@1524 69 }
Chris@1524 70
Chris@1524 71 void separatorPipe() {
Chris@1524 72 CSVFormat f;
Chris@1524 73 QVERIFY(f.guessFormatFor(csvDir.filePath("separator-pipe.csv")));
Chris@1524 74 QCOMPARE(f.getSeparator(), QChar('|'));
Chris@1524 75 // differs from the others
Chris@1524 76 QCOMPARE(f.getColumnCount(), 4);
Chris@1524 77 }
Chris@1524 78
Chris@1524 79 void separatorSpace() {
Chris@1524 80 CSVFormat f;
Chris@1524 81 QVERIFY(f.guessFormatFor(csvDir.filePath("separator-space.csv")));
Chris@1524 82 QCOMPARE(f.getSeparator(), QChar(' '));
Chris@1524 83 // NB fields are separated by 1 or more spaces, not necessarily exactly 1
Chris@1524 84 QCOMPARE(f.getColumnCount(), 3);
Chris@1524 85 }
Chris@1524 86
Chris@1524 87 void separatorColon() {
Chris@1524 88 CSVFormat f;
Chris@1524 89 QVERIFY(f.guessFormatFor(csvDir.filePath("separator-colon.csv")));
Chris@1524 90 QCOMPARE(f.getSeparator(), QChar(':'));
Chris@1524 91 QCOMPARE(f.getColumnCount(), 3);
Chris@1524 92 }
Chris@1524 93
Chris@1585 94 void plausibleSeparators() {
Chris@1585 95 CSVFormat f;
Chris@1585 96 QVERIFY(f.guessFormatFor(csvDir.filePath("separator-many.csv")));
Chris@1585 97 std::set<QChar> p;
Chris@1585 98 p.insert(QChar('|'));
Chris@1585 99 p.insert(QChar(','));
Chris@1585 100 p.insert(QChar(':'));
Chris@1585 101 p.insert(QChar(' '));
Chris@1585 102 std::set<QChar> actual = f.getPlausibleSeparators();
Chris@1585 103 QCOMPARE(actual, p);
Chris@1585 104 }
Chris@1585 105
Chris@1524 106 void comment() {
Chris@1524 107 CSVFormat f;
Chris@1524 108 QVERIFY(f.guessFormatFor(csvDir.filePath("comment.csv")));
Chris@1524 109 QCOMPARE(f.getSeparator(), QChar(','));
Chris@1524 110 QCOMPARE(f.getColumnCount(), 4);
Chris@1345 111 }
Chris@1345 112
Chris@1524 113 void qualities() {
Chris@1524 114 CSVFormat f;
Chris@1524 115 QVERIFY(f.guessFormatFor(csvDir.filePath("column-qualities.csv")));
Chris@1524 116 QCOMPARE(f.getSeparator(), QChar(','));
Chris@1524 117 QCOMPARE(f.getColumnCount(), 7);
Chris@1524 118 QList<CSVFormat::ColumnQualities> q = f.getColumnQualities();
Chris@1524 119 QList<CSVFormat::ColumnQualities> expected;
Chris@1524 120 expected << 0;
Chris@1524 121 expected << CSVFormat::ColumnQualities(CSVFormat::ColumnNumeric |
Chris@1524 122 CSVFormat::ColumnIntegral |
Chris@1524 123 CSVFormat::ColumnIncreasing);
Chris@1524 124 expected << CSVFormat::ColumnQualities(CSVFormat::ColumnNumeric |
Chris@1524 125 CSVFormat::ColumnIntegral |
Chris@1524 126 CSVFormat::ColumnIncreasing |
Chris@1524 127 CSVFormat::ColumnLarge);
Chris@1524 128 expected << CSVFormat::ColumnQualities(CSVFormat::ColumnNumeric);
Chris@1524 129 expected << CSVFormat::ColumnQualities(CSVFormat::ColumnNumeric |
Chris@1524 130 CSVFormat::ColumnIncreasing);
Chris@1524 131 expected << CSVFormat::ColumnQualities(CSVFormat::ColumnNumeric |
Chris@1524 132 CSVFormat::ColumnSmall |
Chris@1524 133 CSVFormat::ColumnSigned);
Chris@1524 134 expected << CSVFormat::ColumnQualities(CSVFormat::ColumnNumeric |
Chris@1524 135 CSVFormat::ColumnIntegral |
Chris@1524 136 CSVFormat::ColumnIncreasing |
Chris@1524 137 CSVFormat::ColumnNearEmpty);
Chris@1524 138 QCOMPARE(q, expected);
Chris@1359 139 }
Chris@1525 140
Chris@1525 141 void modelType1DSamples() {
Chris@1525 142 CSVFormat f;
Chris@1525 143 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-1d-samples.csv")));
Chris@1525 144 QCOMPARE(f.getColumnCount(), 1);
Chris@1525 145 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 146 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 147 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeAudioFrames);
Chris@1525 148 QCOMPARE(f.getModelType(), CSVFormat::OneDimensionalModel);
Chris@1525 149 }
Chris@1525 150
Chris@1525 151 void modelType1DSeconds() {
Chris@1525 152 CSVFormat f;
Chris@1525 153 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-1d-seconds.csv")));
Chris@1525 154 QCOMPARE(f.getColumnCount(), 2);
Chris@1525 155 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 156 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnLabel);
Chris@1525 157 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 158 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeSeconds);
Chris@1525 159 QCOMPARE(f.getModelType(), CSVFormat::OneDimensionalModel);
Chris@1525 160 }
Chris@1525 161
Chris@1525 162 void modelType2DSamples() {
Chris@1525 163 CSVFormat f;
Chris@1525 164 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-2d-samples.csv")));
Chris@1525 165 QCOMPARE(f.getColumnCount(), 2);
Chris@1525 166 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 167 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnValue);
Chris@1525 168 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 169 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeAudioFrames);
Chris@1525 170 QCOMPARE(f.getModelType(), CSVFormat::TwoDimensionalModel);
Chris@1525 171 }
Chris@1525 172
Chris@1525 173 void modelType2DSeconds() {
Chris@1525 174 CSVFormat f;
Chris@1525 175 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-2d-seconds.csv")));
Chris@1525 176 QCOMPARE(f.getColumnCount(), 2);
Chris@1525 177 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 178 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnValue);
Chris@1525 179 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 180 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeSeconds);
Chris@1525 181 QCOMPARE(f.getModelType(), CSVFormat::TwoDimensionalModel);
Chris@1525 182 }
Chris@1525 183
Chris@1525 184 void modelType2DImplicit() {
Chris@1525 185 CSVFormat f;
Chris@1525 186 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-2d-implicit.csv")));
Chris@1525 187 QCOMPARE(f.getColumnCount(), 1);
Chris@1525 188 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnValue);
Chris@1525 189 QCOMPARE(f.getTimingType(), CSVFormat::ImplicitTiming);
Chris@1525 190 }
Chris@1525 191
Chris@1525 192 void modelType2DEndTimeSamples() {
Chris@1525 193 CSVFormat f;
Chris@1525 194 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-2d-endtime-samples.csv")));
Chris@1525 195 QCOMPARE(f.getColumnCount(), 3);
Chris@1525 196 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 197 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnEndTime);
Chris@1525 198 QCOMPARE(f.getColumnPurpose(2), CSVFormat::ColumnValue);
Chris@1525 199 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 200 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeAudioFrames);
Chris@1525 201 QCOMPARE(f.getModelType(), CSVFormat::TwoDimensionalModelWithDuration);
Chris@1525 202 }
Chris@1525 203
Chris@1525 204 void modelType2DEndTimeSeconds() {
Chris@1525 205 CSVFormat f;
Chris@1525 206 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-2d-endtime-seconds.csv")));
Chris@1525 207 QCOMPARE(f.getColumnCount(), 3);
Chris@1525 208 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 209 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnEndTime);
Chris@1525 210 QCOMPARE(f.getColumnPurpose(2), CSVFormat::ColumnValue);
Chris@1525 211 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 212 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeSeconds);
Chris@1525 213 QCOMPARE(f.getModelType(), CSVFormat::TwoDimensionalModelWithDuration);
Chris@1525 214 }
Chris@1525 215
Chris@1525 216 void modelType2DDurationSamples() {
Chris@1525 217 CSVFormat f;
Chris@1525 218 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-2d-duration-samples.csv")));
Chris@1525 219 QCOMPARE(f.getColumnCount(), 3);
Chris@1525 220 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 221 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnDuration);
Chris@1525 222 QCOMPARE(f.getColumnPurpose(2), CSVFormat::ColumnValue);
Chris@1525 223 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 224 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeAudioFrames);
Chris@1525 225 QCOMPARE(f.getModelType(), CSVFormat::TwoDimensionalModelWithDuration);
Chris@1525 226 }
Chris@1525 227
Chris@1525 228 void modelType2DDurationSeconds() {
Chris@1525 229 CSVFormat f;
Chris@1525 230 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-2d-duration-seconds.csv")));
Chris@1525 231 QCOMPARE(f.getColumnCount(), 3);
Chris@1525 232 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 233 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnDuration);
Chris@1525 234 QCOMPARE(f.getColumnPurpose(2), CSVFormat::ColumnValue);
Chris@1525 235 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 236 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeSeconds);
Chris@1525 237 QCOMPARE(f.getModelType(), CSVFormat::TwoDimensionalModelWithDuration);
Chris@1525 238 }
Chris@1525 239
Chris@1525 240 void modelType3DSamples() {
Chris@1525 241 CSVFormat f;
Chris@1525 242 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-3d-samples.csv")));
Chris@1525 243 QCOMPARE(f.getColumnCount(), 7);
Chris@1525 244 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 245 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnValue);
Chris@1525 246 QCOMPARE(f.getColumnPurpose(2), CSVFormat::ColumnValue);
Chris@1525 247 QCOMPARE(f.getColumnPurpose(3), CSVFormat::ColumnValue);
Chris@1525 248 QCOMPARE(f.getColumnPurpose(4), CSVFormat::ColumnValue);
Chris@1525 249 QCOMPARE(f.getColumnPurpose(5), CSVFormat::ColumnValue);
Chris@1525 250 QCOMPARE(f.getColumnPurpose(6), CSVFormat::ColumnValue);
Chris@1525 251 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 252 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeAudioFrames);
Chris@1525 253 QCOMPARE(f.getModelType(), CSVFormat::ThreeDimensionalModel);
Chris@1525 254 }
Chris@1525 255
Chris@1525 256 void modelType3DSeconds() {
Chris@1525 257 CSVFormat f;
Chris@1525 258 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-3d-seconds.csv")));
Chris@1525 259 QCOMPARE(f.getColumnCount(), 7);
Chris@1525 260 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnStartTime);
Chris@1525 261 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnValue);
Chris@1525 262 QCOMPARE(f.getColumnPurpose(2), CSVFormat::ColumnValue);
Chris@1525 263 QCOMPARE(f.getColumnPurpose(3), CSVFormat::ColumnValue);
Chris@1525 264 QCOMPARE(f.getColumnPurpose(4), CSVFormat::ColumnValue);
Chris@1525 265 QCOMPARE(f.getColumnPurpose(5), CSVFormat::ColumnValue);
Chris@1525 266 QCOMPARE(f.getColumnPurpose(6), CSVFormat::ColumnValue);
Chris@1525 267 QCOMPARE(f.getTimingType(), CSVFormat::ExplicitTiming);
Chris@1525 268 QCOMPARE(f.getTimeUnits(), CSVFormat::TimeSeconds);
Chris@1525 269 QCOMPARE(f.getModelType(), CSVFormat::ThreeDimensionalModel);
Chris@1525 270 }
Chris@1525 271
Chris@1525 272 void modelType3DImplicit() {
Chris@1525 273 CSVFormat f;
Chris@1525 274 QVERIFY(f.guessFormatFor(csvDir.filePath("model-type-3d-implicit.csv")));
Chris@1525 275 QCOMPARE(f.getColumnCount(), 6);
Chris@1525 276 QCOMPARE(f.getColumnPurpose(0), CSVFormat::ColumnValue);
Chris@1525 277 QCOMPARE(f.getColumnPurpose(1), CSVFormat::ColumnValue);
Chris@1525 278 QCOMPARE(f.getColumnPurpose(2), CSVFormat::ColumnValue);
Chris@1525 279 QCOMPARE(f.getColumnPurpose(3), CSVFormat::ColumnValue);
Chris@1525 280 QCOMPARE(f.getColumnPurpose(4), CSVFormat::ColumnValue);
Chris@1525 281 QCOMPARE(f.getColumnPurpose(5), CSVFormat::ColumnValue);
Chris@1525 282 QCOMPARE(f.getTimingType(), CSVFormat::ImplicitTiming);
Chris@1525 283 QCOMPARE(f.getModelType(), CSVFormat::ThreeDimensionalModel);
Chris@1525 284 }
Chris@1525 285
Chris@1345 286 };
Chris@1345 287
Chris@1345 288 #endif