Mercurial > hg > svcore
changeset 1698:dbd13eb7dad1
Add tests for audio file readers presented with empty or nonsense input
author | Chris Cannam |
---|---|
date | Fri, 03 May 2019 13:33:53 +0100 |
parents | ea1aa24ebf89 |
children | ad33d6c10738 5d4831c2e8aa |
files | data/fileio/AudioFileReaderFactory.cpp data/fileio/test/AudioFileReaderTest.h data/fileio/test/BogusAudioFileReaderTest.h data/fileio/test/EncodingTest.h data/fileio/test/UnsupportedFormat.h data/fileio/test/files.pri data/fileio/test/svcore-data-fileio-test.cpp |
diffstat | 7 files changed, 175 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/data/fileio/AudioFileReaderFactory.cpp Tue Apr 23 16:17:13 2019 +0100 +++ b/data/fileio/AudioFileReaderFactory.cpp Fri May 03 13:33:53 2019 +0100 @@ -78,12 +78,12 @@ SVDEBUG << "AudioFileReaderFactory: local filename \"" << source.getLocalFilename() << "\", content type \"" << source.getContentType() << "\"" << endl; if (!source.isOK()) { - SVCERR << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl; + SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl; return nullptr; } if (!source.isAvailable()) { - SVCERR << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl; + SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl; return nullptr; } @@ -213,11 +213,11 @@ } } - SVCERR << "AudioFileReaderFactory::Failed to create a reader for " - << "url \"" << source.getLocation() - << "\" (local filename \"" << source.getLocalFilename() - << "\", content type \"" - << source.getContentType() << "\")" << endl; + SVDEBUG << "AudioFileReaderFactory::Failed to create a reader for " + << "url \"" << source.getLocation() + << "\" (local filename \"" << source.getLocalFilename() + << "\", content type \"" + << source.getContentType() << "\")" << endl; return nullptr; }
--- a/data/fileio/test/AudioFileReaderTest.h Tue Apr 23 16:17:13 2019 +0100 +++ b/data/fileio/test/AudioFileReaderTest.h Fri May 03 13:33:53 2019 +0100 @@ -21,6 +21,7 @@ #include "../WavFileWriter.h" #include "AudioTestData.h" +#include "UnsupportedFormat.h" #include <cmath> @@ -73,7 +74,7 @@ bitdepth = bits[2].toInt(); } } - + void getExpectedThresholds(QString format, QString filename, bool resampled, @@ -305,11 +306,13 @@ (audioDir + "/" + format + "/" + audiofile, params); if (!reader) { + if (isLegitimatelyUnsupported(format)) { #if ( QT_VERSION >= 0x050000 ) - QSKIP("Unsupported file, skipping"); + QSKIP("Unsupported file, skipping"); #else - QSKIP("Unsupported file, skipping", SkipSingle); + QSKIP("Unsupported file, skipping", SkipSingle); #endif + } } QString extension;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fileio/test/BogusAudioFileReaderTest.h Fri May 03 13:33:53 2019 +0100 @@ -0,0 +1,94 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef SV_BOGUS_AUDIO_FILE_READER_TEST_H +#define SV_BOGUS_AUDIO_FILE_READER_TEST_H + +#include "../AudioFileReaderFactory.h" + +#include "base/TempDirectory.h" + +#include <QObject> +#include <QtTest> +#include <QDir> + +// Tests for malformed audio files - primarily to ensure we don't crash + +class BogusAudioFileReaderTest : public QObject +{ + Q_OBJECT + +private slots: + void bogus_data() + { + QTest::addColumn<QString>("format"); + QTest::addColumn<bool>("empty"); + QStringList patterns = AudioFileReaderFactory::getKnownExtensions() + .split(" ", QString::SkipEmptyParts); + + for (auto p: patterns) { + + QStringList bits = p.split("."); + QString extension = bits[bits.size()-1]; + + QString testName = QString("%1, empty").arg(extension); + QTest::newRow(strdup(testName.toLocal8Bit().data())) + << extension << true; + + testName = QString("%1, nonsense").arg(extension); + QTest::newRow(strdup(testName.toLocal8Bit().data())) + << extension << false; + } + } + + void bogus() + { + QFETCH(QString, format); + QFETCH(bool, empty); + + if (format == "au") { // au is headerless, so any file is legal +#if ( QT_VERSION >= 0x050000 ) + QSKIP("Skipping headerless file"); +#else + QSKIP("Skipping headerless file", SkipSingle); +#endif + } + + QString tmpdir = TempDirectory::getInstance()->getPath(); + + QString path = QString("%1/%2.%3") + .arg(tmpdir) + .arg(empty ? "empty" : "nonsense") + .arg(format); + QFile f(path); + if (!f.open(QIODevice::WriteOnly)) { + std::cerr << "Failed to create temporary file " + << path << std::endl; + throw std::runtime_error("Failed to create temporary file"); + } + if (!empty) { + for (int i = 0; i < 1000; ++i) { + f.write("weeble"); + } + } + f.close(); + + AudioFileReader *reader = + AudioFileReaderFactory::createReader(path, {}); + QCOMPARE((void *)reader, nullptr); + } + +}; + +#endif
--- a/data/fileio/test/EncodingTest.h Tue Apr 23 16:17:13 2019 +0100 +++ b/data/fileio/test/EncodingTest.h Fri May 03 13:33:53 2019 +0100 @@ -22,6 +22,8 @@ #include "../AudioFileReader.h" #include "../WavFileWriter.h" +#include "UnsupportedFormat.h" + #include <cmath> #include <QObject> @@ -132,13 +134,18 @@ QFETCH(QString, audiofile); + QStringList fileAndExt = audiofile.split("."); + QString extension = fileAndExt[1]; + if (!AudioFileReaderFactory::isSupported(encodingDir + "/" + audiofile)) { + if (isLegitimatelyUnsupported(extension)) { #if ( QT_VERSION >= 0x050000 ) - QSKIP("Known unsupported file, skipping"); + QSKIP("Known unsupported file, skipping"); #else - QSKIP("Known unsupported file, skipping", SkipSingle); + QSKIP("Known unsupported file, skipping", SkipSingle); #endif + } } AudioFileReaderFactory::Parameters params; @@ -163,22 +170,26 @@ QFETCH(QString, audiofile); + QStringList fileAndExt = audiofile.split("."); + QString file = fileAndExt[0]; + QString extension = fileAndExt[1]; + AudioFileReaderFactory::Parameters params; AudioFileReader *reader = AudioFileReaderFactory::createReader (encodingDir + "/" + audiofile, params); if (!reader) { + if (isLegitimatelyUnsupported(extension)) { #if ( QT_VERSION >= 0x050000 ) - QSKIP("Unsupported file, skipping"); + QSKIP("Unsupported file, skipping"); #else - QSKIP("Unsupported file, skipping", SkipSingle); + QSKIP("Unsupported file, skipping", SkipSingle); #endif + } } - QStringList fileAndExt = audiofile.split("."); - QString file = fileAndExt[0]; - QString extension = fileAndExt[1]; + QVERIFY(reader != nullptr); if (extension == "wav") { @@ -188,12 +199,6 @@ } else { -//#if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND)) -// if (extension == "ogg") { -// QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata"); -// } -//#endif - auto blah = reader->getInterleavedFrames(0, 10); QString title = reader->getTitle(); @@ -261,25 +266,23 @@ return; } -//#if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND)) -// if (extension == "ogg") { -// QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata"); -// } -//#endif - AudioFileReaderFactory::Parameters params; AudioFileReader *reader = AudioFileReaderFactory::createReader (encodingDir + "/" + audiofile, params); if (!reader) { + if (isLegitimatelyUnsupported(extension)) { #if ( QT_VERSION >= 0x050000 ) - QSKIP("Unsupported file, skipping"); + QSKIP("Unsupported file, skipping"); #else - QSKIP("Unsupported file, skipping", SkipSingle); + QSKIP("Unsupported file, skipping", SkipSingle); #endif + } } + QVERIFY(reader != nullptr); + QString title = reader->getTitle(); QVERIFY(title != QString());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fileio/test/UnsupportedFormat.h Fri May 03 13:33:53 2019 +0100 @@ -0,0 +1,35 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2013 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef SV_UNSUPPORTED_FORMAT_H +#define SV_UNSUPPORTED_FORMAT_H + +static bool isLegitimatelyUnsupported(QString format) { + +#ifdef Q_OS_WIN + return (format == "apple_lossless"); +#else +#ifdef Q_OS_MAC + return (format == "wma"); +#else + return (format == "aac" || + format == "apple_lossless" || + format == "m4a" || + format == "wma"); +#endif +#endif +} + +#endif
--- a/data/fileio/test/files.pri Tue Apr 23 16:17:13 2019 +0100 +++ b/data/fileio/test/files.pri Fri May 03 13:33:53 2019 +0100 @@ -2,6 +2,8 @@ TEST_HEADERS += \ ../../model/test/MockWaveModel.h \ AudioFileReaderTest.h \ + UnsupportedFormat.h \ + BogusAudioFileReaderTest.h \ AudioFileWriterTest.h \ AudioTestData.h \ EncodingTest.h \
--- a/data/fileio/test/svcore-data-fileio-test.cpp Tue Apr 23 16:17:13 2019 +0100 +++ b/data/fileio/test/svcore-data-fileio-test.cpp Fri May 03 13:33:53 2019 +0100 @@ -13,6 +13,7 @@ */ #include "AudioFileReaderTest.h" +#include "BogusAudioFileReaderTest.h" #include "AudioFileWriterTest.h" #include "EncodingTest.h" #include "MIDIFileReaderTest.h" @@ -65,6 +66,12 @@ } { + BogusAudioFileReaderTest t; + if (QTest::qExec(&t, argc, argv) == 0) ++good; + else ++bad; + } + + { EncodingTest t(testDir); if (QTest::qExec(&t, argc, argv) == 0) ++good; else ++bad;