diff --git a/CMakeLists.txt b/CMakeLists.txt index 90fc98d5..84454a31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE if (CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_SYSTEM_NAME MATCHES Linux) set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -ansi -Wundef -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common") - set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-exceptions -fno-check-new -fno-common") + set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-check-new -fno-common") endif (CMAKE_SYSTEM_NAME MATCHES Linux) endif (CMAKE_COMPILER_IS_GNUCXX) if(MSVC) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 694b15c4..2db674c5 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -19,3 +19,6 @@ IF(ZLIB_FOUND) ELSE(ZLIB_FOUND) SET(HAVE_ZLIB 0) ENDIF(ZLIB_FOUND) + +SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) +FIND_PACKAGE(CppUnit) diff --git a/cmake/modules/FindCppUnit.cmake b/cmake/modules/FindCppUnit.cmake new file mode 100644 index 00000000..08dd42da --- /dev/null +++ b/cmake/modules/FindCppUnit.cmake @@ -0,0 +1,28 @@ +INCLUDE(UsePkgConfig) +PKGCONFIG(cppunit _CppUnitIncDir _CppUnitLinkDir _CppUnitLinkFlags _CppUnitCflags) + +FIND_PATH(CPPUNIT_INCLUDE_DIR cppunit/TestCase.h + ${_CppUnitIncDir} + /usr/local/include + /usr/include +) + +FIND_LIBRARY(CPPUNIT_LIBRARIES cppunit + ${_CppUnitLinkDir} + /usr/local/lib + /usr/lib +) + +IF (CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) + SET(CPPUNIT_FOUND TRUE) +ENDIF (CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) + +IF (CPPUNIT_FOUND) + IF (NOT CppUnit_FIND_QUIETLY) + MESSAGE(STATUS "Found CppUnit: ${CPPUNIT_LIBRARIES}") + ENDIF (NOT CppUnit_FIND_QUIETLY) +ELSE (CPPUNIT_FOUND) + IF (CppUnit_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find CppUnit") + ENDIF (CppUnit_FIND_REQUIRED) +ENDIF (CPPUNIT_FOUND) diff --git a/configure.in.in b/configure.in.in index d449eacc..0a3414ba 100644 --- a/configure.in.in +++ b/configure.in.in @@ -63,7 +63,7 @@ AC_CHECK_COMPILERS dnl CXXFLAGS="$NOOPT_CXXFLAGS" dnl __kdevelop[noopt]__ dnl CFLAGS="$NOOPT_CFLAGS" dnl __kdevelop[noopt]__ -dnl CXXFLAGS="$CXXFLAGS $USE_EXCEPTIONS" dnl __kdevelop[exc]__ +CXXFLAGS="$CXXFLAGS $USE_EXCEPTIONS" dnl __kdevelop[exc]__ dnl create only shared libtool-libraries AC_ENABLE_SHARED(yes) @@ -113,3 +113,21 @@ AC_DEFUN([AC_NO_ZLIB], AC_CHECK_HEADER(zlib.h, AC_HAVE_ZLIB, AC_NO_ZLIB) AM_CONDITIONAL(link_zlib, test x$have_zlib = xtrue) + +AC_DEFUN([AC_HAVE_CPPUNIT], +[ + AC_DEFINE(HAVE_CPPUNIT, 1, [have cppunit]) + have_cppunit=true +]) + +AC_DEFUN([AC_NO_CPPUNIT], +[ + AC_DEFINE(HAVE_CPPUNIT, 0, [have cppunit]) + have_cppunit=false +]) + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_CHECK_HEADER(cppunit/extensions/HelperMacros.h, AC_HAVE_CPPUNIT, AC_NO_CPPUNIT) +AC_LANG_RESTORE +AM_CONDITIONAL(build_tests, test x$have_cppunit = xtrue) diff --git a/taglib/Makefile.am b/taglib/Makefile.am index 6a2e700e..7337eb3f 100644 --- a/taglib/Makefile.am +++ b/taglib/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = toolkit mpeg ogg flac ape mpc wavpack +SUBDIRS = toolkit mpeg ogg flac ape mpc wavpack speex INCLUDES = \ -I$(top_srcdir)/taglib \ diff --git a/taglib/speex/Makefile.am b/taglib/speex/Makefile.am index da47fa8a..ef95d5bd 100644 --- a/taglib/speex/Makefile.am +++ b/taglib/speex/Makefile.am @@ -1,5 +1,6 @@ INCLUDES = \ -I$(top_srcdir)/taglib \ + -I$(top_srcdir)/taglib/toolkit \ -I$(top_srcdir)/taglib/ogg \ $(all_includes) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8ce01c8c..34aa7fab 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,16 +1,32 @@ if(BUILD_TESTS) -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../taglib - ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit - ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2 ) - -########### next target ############### - -SET(toolkit-test_SRCS - toolkit-test.cpp +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/../taglib + ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit + ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1 + ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2 + ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2/frames + ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg ) -ADD_EXECUTABLE(toolkit-test ${toolkit-test_SRCS}) +SET(test_runner_SRCS + main.cpp + test_list.cpp + test_map.cpp + test_synchdata.cpp + test_bytevector.cpp + test_string.cpp + test_fileref.cpp + test_id3v1.cpp + test_id3v2.cpp +) + +ADD_EXECUTABLE(test_runner ${test_runner_SRCS}) +TARGET_LINK_LIBRARIES(test_runner tag ${CPPUNIT_LIBRARIES}) + +ADD_CUSTOM_TARGET(check + ./test_runner + DEPENDS test_runner +) -TARGET_LINK_LIBRARIES(toolkit-test tag ) endif(BUILD_TESTS) diff --git a/tests/Makefile.am b/tests/Makefile.am index b8f68743..47a6b3f0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,10 +1,24 @@ INCLUDES = \ -I$(top_srcdir)/taglib\ -I$(top_srcdir)/taglib/toolkit \ - -I$(top_srcdir)/taglib/mpeg/id3v2 + -I$(top_srcdir)/taglib/mpeg \ + -I$(top_srcdir)/taglib/mpeg/id3v1 \ + -I$(top_srcdir)/taglib/mpeg/id3v2 \ + -I$(top_srcdir)/taglib/mpeg/id3v2/frames -LDADD = ../taglib/libtag.la +test_runner_SOURCES = \ + main.cpp \ + test_list.cpp \ + test_map.cpp \ + test_synchdata.cpp \ + test_bytevector.cpp \ + test_string.cpp \ + test_fileref.cpp \ + test_id3v1.cpp \ + test_id3v2.cpp -check_PROGRAMS = toolkit-test - -toolkit_test_SOURCES = toolkit-test.cpp +if build_tests +TESTS = test_runner +check_PROGRAMS = test_runner +LDADD = ../taglib/libtag.la -lcppunit +endif diff --git a/tests/data/broken-tenc.id3 b/tests/data/broken-tenc.id3 new file mode 100644 index 00000000..80904050 Binary files /dev/null and b/tests/data/broken-tenc.id3 differ diff --git a/tests/data/click.mpc b/tests/data/click.mpc new file mode 100644 index 00000000..a41f14e9 Binary files /dev/null and b/tests/data/click.mpc differ diff --git a/tests/data/empty.ogg b/tests/data/empty.ogg new file mode 100644 index 00000000..aa533104 Binary files /dev/null and b/tests/data/empty.ogg differ diff --git a/tests/data/empty.spx b/tests/data/empty.spx new file mode 100644 index 00000000..70572b45 Binary files /dev/null and b/tests/data/empty.spx differ diff --git a/tests/data/no-tags.flac b/tests/data/no-tags.flac new file mode 100644 index 00000000..41714416 Binary files /dev/null and b/tests/data/no-tags.flac differ diff --git a/tests/data/unsynch.id3 b/tests/data/unsynch.id3 new file mode 100644 index 00000000..cfe6ee1a Binary files /dev/null and b/tests/data/unsynch.id3 differ diff --git a/tests/data/xing.mp3 b/tests/data/xing.mp3 new file mode 100644 index 00000000..0c880151 Binary files /dev/null and b/tests/data/xing.mp3 differ diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 00000000..348751e4 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) +{ + std::string testPath = (argc > 1) ? std::string(argv[1]) : ""; + + // Create the event manager and test controller + CppUnit::TestResult controller; + + // Add a listener that colllects test result + CppUnit::TestResultCollector result; + controller.addListener(&result); + + // Add a listener that print dots as test run. + CppUnit::BriefTestProgressListener progress; + controller.addListener(&progress); + + // Add the top suite to the test runner + CppUnit::TestRunner runner; + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); + + try { + std::cout << "Running " << testPath; + runner.run(controller, testPath); + + std::cerr << std::endl; + + // Print test in a compiler compatible format. + CppUnit::CompilerOutputter outputter(&result, std::cerr); + outputter.write(); + } + catch(std::invalid_argument &e){ + std::cerr << std::endl + << "ERROR: " << e.what() + << std::endl; + return 0; + } + + return result.wasSuccessful() ? 0 : 1; +} diff --git a/tests/test_bytevector.cpp b/tests/test_bytevector.cpp new file mode 100644 index 00000000..56789fee --- /dev/null +++ b/tests/test_bytevector.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2003 Scott Wheeler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +using namespace std; +using namespace TagLib; + +class TestByteVector : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestByteVector); + CPPUNIT_TEST(testByteVector); + CPPUNIT_TEST(testFind1); + CPPUNIT_TEST(testRfind1); + CPPUNIT_TEST(testRfind2); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testConversion(unsigned int i, unsigned char a, unsigned char b, unsigned char c, unsigned char d) + { + ByteVector v(4, 0); + + v[3] = a; + v[2] = b; + v[1] = c; + v[0] = d; + CPPUNIT_ASSERT(v.toUInt(false) == i); + + v[0] = a; + v[1] = b; + v[2] = c; + v[3] = d; + CPPUNIT_ASSERT(v.toUInt() == i); + } + + void testByteVector() + { + ByteVector v("foobar"); + + CPPUNIT_ASSERT(v.find("ob") == 2); + CPPUNIT_ASSERT(v.find('b') == 3); + + ByteVector n(4, 0); + n[0] = 1; + CPPUNIT_ASSERT(n.toUInt(true) == 16777216); + CPPUNIT_ASSERT(n.toUInt(false) == 1); + CPPUNIT_ASSERT(ByteVector::fromUInt(16777216, true) == n); + CPPUNIT_ASSERT(ByteVector::fromUInt(1, false) == n); + + CPPUNIT_ASSERT(ByteVector::fromUInt(0xa0).toUInt() == 0xa0); + + testConversion(0x000000a0, 0x00, 0x00, 0x00, 0xa0); + testConversion(0xd50bf072, 0xd5, 0x0b, 0xf0, 0x72); + + ByteVector intVector(2, 0); + intVector[0] = char(0xfc); + intVector[1] = char(0x00); + CPPUNIT_ASSERT(intVector.toShort() == -1024); + intVector[0] = char(0x04); + intVector[1] = char(0x00); + CPPUNIT_ASSERT(intVector.toShort() == 1024); + + CPPUNIT_ASSERT(ByteVector::fromLongLong(1).toLongLong() == 1); + CPPUNIT_ASSERT(ByteVector::fromLongLong(0).toLongLong() == 0); + CPPUNIT_ASSERT(ByteVector::fromLongLong(0xffffffffffffffffLL).toLongLong() == -1); + CPPUNIT_ASSERT(ByteVector::fromLongLong(0xfffffffffffffffeLL).toLongLong() == -2); + CPPUNIT_ASSERT(ByteVector::fromLongLong(1024).toLongLong() == 1024); + + ByteVector a1("foo"); + a1.append("bar"); + CPPUNIT_ASSERT(a1 == "foobar"); + + ByteVector a2("foo"); + a2.append("b"); + CPPUNIT_ASSERT(a2 == "foob"); + + ByteVector a3; + a3.append("b"); + CPPUNIT_ASSERT(a3 == "b"); + + ByteVector s1("foo"); + CPPUNIT_ASSERT(ByteVectorList::split(s1, " ").size() == 1); + + ByteVector s2("f"); + CPPUNIT_ASSERT(ByteVectorList::split(s2, " ").size() == 1); + + + CPPUNIT_ASSERT(ByteVector().size() == 0); + CPPUNIT_ASSERT(ByteVector("asdf").clear().size() == 0); + CPPUNIT_ASSERT(ByteVector("asdf").clear() == ByteVector()); + } + + void testFind1() + { + CPPUNIT_ASSERT_EQUAL(4, ByteVector("....SggO."). find("SggO")); + CPPUNIT_ASSERT_EQUAL(4, ByteVector("....SggO."). find("SggO", 0)); + CPPUNIT_ASSERT_EQUAL(4, ByteVector("....SggO."). find("SggO", 1)); + CPPUNIT_ASSERT_EQUAL(4, ByteVector("....SggO."). find("SggO", 2)); + CPPUNIT_ASSERT_EQUAL(4, ByteVector("....SggO."). find("SggO", 3)); + CPPUNIT_ASSERT_EQUAL(4, ByteVector("....SggO."). find("SggO", 4)); + CPPUNIT_ASSERT_EQUAL(-1, ByteVector("....SggO."). find("SggO", 5)); + CPPUNIT_ASSERT_EQUAL(-1, ByteVector("....SggO."). find("SggO", 6)); + CPPUNIT_ASSERT_EQUAL(-1, ByteVector("....SggO."). find("SggO", 7)); + CPPUNIT_ASSERT_EQUAL(-1, ByteVector("....SggO."). find("SggO", 8)); + } + + void testRfind1() + { + CPPUNIT_ASSERT_EQUAL(-1, ByteVector(".OggS....").rfind("OggS", 0)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 1)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 2)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 3)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 4)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 5)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 6)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 7)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS", 8)); + CPPUNIT_ASSERT_EQUAL(1, ByteVector(".OggS....").rfind("OggS")); + } + + void testRfind2() + { + ByteVector r0("**************"); + ByteVector r1("OggS**********"); + ByteVector r2("**********OggS"); + ByteVector r3("OggS******OggS"); + ByteVector r4("OggS*OggS*OggS"); + + CPPUNIT_ASSERT_EQUAL(-1, r0.find("OggS")); + CPPUNIT_ASSERT_EQUAL(-1, r0.rfind("OggS")); + CPPUNIT_ASSERT_EQUAL(0, r1.find("OggS")); + CPPUNIT_ASSERT_EQUAL(0, r1.rfind("OggS")); + CPPUNIT_ASSERT_EQUAL(10, r2.find("OggS")); + CPPUNIT_ASSERT_EQUAL(10, r2.rfind("OggS")); + CPPUNIT_ASSERT_EQUAL(0, r3.find("OggS")); + CPPUNIT_ASSERT_EQUAL(10, r3.rfind("OggS")); + CPPUNIT_ASSERT_EQUAL(10, r4.rfind("OggS")); + CPPUNIT_ASSERT_EQUAL(0, r4.rfind("OggS", 0)); + CPPUNIT_ASSERT_EQUAL(5, r4.rfind("OggS", 7)); + CPPUNIT_ASSERT_EQUAL(10, r4.rfind("OggS", 12)); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVector); diff --git a/tests/test_fileref.cpp b/tests/test_fileref.cpp new file mode 100644 index 00000000..c862cdd0 --- /dev/null +++ b/tests/test_fileref.cpp @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include "utils.h" + +using namespace std; +using namespace TagLib; + +class TestFileRef : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestFileRef); + CPPUNIT_TEST(testMusepack); + CPPUNIT_TEST(testVorbis); + CPPUNIT_TEST(testSpeex); + CPPUNIT_TEST(testFLAC); + CPPUNIT_TEST(testMP3); + CPPUNIT_TEST_SUITE_END(); + +public: + + void fileRefSave(const string &filename, const string &ext) + { + string newname = copyFile(filename, ext); + + FileRef *f = new FileRef(newname.c_str()); + CPPUNIT_ASSERT(!f->isNull()); + f->tag()->setArtist("test artist"); + f->tag()->setTitle("test title"); + f->tag()->setGenre("Test!"); + f->tag()->setAlbum("albummmm"); + f->tag()->setTrack(5); + f->tag()->setYear(2020); + f->save(); + delete f; + + f = new FileRef(newname.c_str()); + CPPUNIT_ASSERT(!f->isNull()); + CPPUNIT_ASSERT_EQUAL(f->tag()->artist(), String("test artist")); + CPPUNIT_ASSERT_EQUAL(f->tag()->title(), String("test title")); + CPPUNIT_ASSERT_EQUAL(f->tag()->genre(), String("Test!")); + CPPUNIT_ASSERT_EQUAL(f->tag()->album(), String("albummmm")); + CPPUNIT_ASSERT_EQUAL(f->tag()->track(), TagLib::uint(5)); + CPPUNIT_ASSERT_EQUAL(f->tag()->year(), TagLib::uint(2020)); + f->tag()->setArtist("ttest artist"); + f->tag()->setTitle("ytest title"); + f->tag()->setGenre("uTest!"); + f->tag()->setAlbum("ialbummmm"); + f->tag()->setTrack(7); + f->tag()->setYear(2080); + f->save(); + delete f; + + f = new FileRef(newname.c_str()); + CPPUNIT_ASSERT(!f->isNull()); + CPPUNIT_ASSERT_EQUAL(f->tag()->artist(), String("ttest artist")); + CPPUNIT_ASSERT_EQUAL(f->tag()->title(), String("ytest title")); + CPPUNIT_ASSERT_EQUAL(f->tag()->genre(), String("uTest!")); + CPPUNIT_ASSERT_EQUAL(f->tag()->album(), String("ialbummmm")); + CPPUNIT_ASSERT_EQUAL(f->tag()->track(), TagLib::uint(7)); + CPPUNIT_ASSERT_EQUAL(f->tag()->year(), TagLib::uint(2080)); + delete f; + + deleteFile(newname); + } + + void testMusepack() + { + fileRefSave("click", ".mpc"); + } + + void testVorbis() + { + fileRefSave("empty", ".ogg"); + } + + void testSpeex() + { + fileRefSave("empty", ".spx"); + } + + void testFLAC() + { + fileRefSave("no-tags", ".flac"); + } + + void testMP3() + { + fileRefSave("xing", ".mp3"); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestFileRef); diff --git a/tests/test_id3v1.cpp b/tests/test_id3v1.cpp new file mode 100644 index 00000000..308225c2 --- /dev/null +++ b/tests/test_id3v1.cpp @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +using namespace std; +using namespace TagLib; + +class TestID3v1 : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestID3v1); + CPPUNIT_TEST(testStripWhiteSpace); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testStripWhiteSpace() + { + ID3v1::StringHandler h; + CPPUNIT_ASSERT_EQUAL(String("Foo"), h.parse(ByteVector("Foo "))); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v1); diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp new file mode 100644 index 00000000..bb6db558 --- /dev/null +++ b/tests/test_id3v2.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace TagLib; + +class TestID3v2 : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestID3v2); + CPPUNIT_TEST(testUnsynchDecode); + CPPUNIT_TEST(testUTF16BEDelimiter); + CPPUNIT_TEST(testUTF16Delimiter); + CPPUNIT_TEST(testBrokenFrame1); + //CPPUNIT_TEST(testItunes24FrameSize); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testUnsynchDecode() + { + MPEG::File f("data/unsynch.id3", false); + CPPUNIT_ASSERT(f.tag()); + CPPUNIT_ASSERT_EQUAL(String("My babe just cares for me"), f.tag()->title()); + } + + void testUTF16BEDelimiter() + { + ID3v2::TextIdentificationFrame f(ByteVector("TPE1"), String::UTF16BE); + StringList sl; + sl.append("Foo"); + sl.append("Bar"); + f.setText(sl); + CPPUNIT_ASSERT_EQUAL((unsigned int)(4+4+2+1+6+2+6), f.render().size()); + } + + void testUTF16Delimiter() + { + ID3v2::TextIdentificationFrame f(ByteVector("TPE1"), String::UTF16); + StringList sl; + sl.append("Foo"); + sl.append("Bar"); + f.setText(sl); + CPPUNIT_ASSERT_EQUAL((unsigned int)(4+4+2+1+8+2+8), f.render().size()); + } + + void testBrokenFrame1() + { + MPEG::File f("data/broken-tenc.id3", false); + CPPUNIT_ASSERT(f.tag()); + CPPUNIT_ASSERT(!f.ID3v2Tag()->frameListMap().contains("TENC")); + } + + /*void testItunes24FrameSize() + { + MPEG::File f("data/005411.id3", false); + CPPUNIT_ASSERT(f.tag()); + CPPUNIT_ASSERT(f.ID3v2Tag()->frameListMap().contains("TIT2")); + CPPUNIT_ASSERT_EQUAL(String("Sunshine Superman"), f.ID3v2Tag()->frameListMap()["TIT2"].front()->toString()); + }*/ + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v2); diff --git a/tests/test_list.cpp b/tests/test_list.cpp new file mode 100644 index 00000000..39cbaf0a --- /dev/null +++ b/tests/test_list.cpp @@ -0,0 +1,58 @@ +/* Copyright (C) 2003 Scott Wheeler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +using namespace std; +using namespace TagLib; + +class TestList : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestList); + CPPUNIT_TEST(testList); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testList() + { + List l1; + List l2; + List l3; + l1.append(2); + l2.append(3); + l2.append(4); + l1.append(l2); + l1.prepend(1); + l3.append(1); + l3.append(2); + l3.append(3); + l3.append(4); + CPPUNIT_ASSERT(l1 == l3); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestList); diff --git a/tests/test_map.cpp b/tests/test_map.cpp new file mode 100644 index 00000000..b6f77aae --- /dev/null +++ b/tests/test_map.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +using namespace std; +using namespace TagLib; + +class TestMap : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestMap); + CPPUNIT_TEST(testInsert); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testInsert() + { + Map m; + m.insert("foo", 3); + CPPUNIT_ASSERT_EQUAL(3, m["foo"]); + m.insert("foo", 7); + CPPUNIT_ASSERT_EQUAL(7, m["foo"]); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestMap); diff --git a/tests/test_string.cpp b/tests/test_string.cpp new file mode 100644 index 00000000..333a4180 --- /dev/null +++ b/tests/test_string.cpp @@ -0,0 +1,113 @@ +/* Copyright (C) 2003 Scott Wheeler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +using namespace std; +using namespace TagLib; + +class TestString : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestString); + CPPUNIT_TEST(testString); + CPPUNIT_TEST(testUTF16Encode); + CPPUNIT_TEST(testUTF16Decode); + CPPUNIT_TEST_SUITE_END(); + +public: + + void testString() + { + String s = "taglib string"; + ByteVector v = "taglib string"; + CPPUNIT_ASSERT(v == s.data(String::Latin1)); + + char str[] = "taglib string"; + CPPUNIT_ASSERT(strcmp(s.toCString(), str) == 0); + + String unicode("José Carlos", String::UTF8); + CPPUNIT_ASSERT(strcmp(unicode.toCString(), "Jos\xe9 Carlos") == 0); + + String latin = "Jos\xe9 Carlos"; + CPPUNIT_ASSERT(strcmp(latin.toCString(true), "José Carlos") == 0); + + String unicode2(unicode.to8Bit(true), String::UTF8); + CPPUNIT_ASSERT(unicode == unicode2); + + CPPUNIT_ASSERT(strcmp(String::number(0).toCString(), "0") == 0); + CPPUNIT_ASSERT(strcmp(String::number(12345678).toCString(), "12345678") == 0); + CPPUNIT_ASSERT(strcmp(String::number(-12345678).toCString(), "-12345678") == 0); + + String n = "123"; + CPPUNIT_ASSERT(n.toInt() == 123); + + n = "-123"; + CPPUNIT_ASSERT(n.toInt() == -123); + + CPPUNIT_ASSERT(String("0").toInt() == 0); + CPPUNIT_ASSERT(String("1").toInt() == 1); + + CPPUNIT_ASSERT(String(" foo ").stripWhiteSpace() == String("foo")); + CPPUNIT_ASSERT(String("foo ").stripWhiteSpace() == String("foo")); + CPPUNIT_ASSERT(String(" foo").stripWhiteSpace() == String("foo")); + + CPPUNIT_ASSERT(memcmp(String("foo").data(String::Latin1).data(), "foo", 3) == 0); + CPPUNIT_ASSERT(memcmp(String("f").data(String::Latin1).data(), "f", 1) == 0); + + ByteVector utf16 = unicode.data(String::UTF16); + + // Check to make sure that the BOM is there and that the data size is correct + + CPPUNIT_ASSERT(utf16.size() == 2 + (unicode.size() * 2)); + + CPPUNIT_ASSERT(unicode == String(utf16, String::UTF16)); + } + + void testUTF16Encode() + { + String a("foo"); + ByteVector b("\0f\0o\0o", 6); + ByteVector c("f\0o\0o\0", 6); + ByteVector d("\377\376f\0o\0o\0", 8); + CPPUNIT_ASSERT(a.data(String::UTF16BE) != a.data(String::UTF16LE)); + CPPUNIT_ASSERT(b == a.data(String::UTF16BE)); + CPPUNIT_ASSERT(c == a.data(String::UTF16LE)); + CPPUNIT_ASSERT_EQUAL(d, a.data(String::UTF16)); + } + + void testUTF16Decode() + { + String a("foo"); + ByteVector b("\0f\0o\0o", 6); + ByteVector c("f\0o\0o\0", 6); + ByteVector d("\377\376f\0o\0o\0", 8); + CPPUNIT_ASSERT_EQUAL(a, String(b, String::UTF16BE)); + CPPUNIT_ASSERT_EQUAL(a, String(c, String::UTF16LE)); + CPPUNIT_ASSERT_EQUAL(a, String(d, String::UTF16)); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestString); diff --git a/tests/test_synchdata.cpp b/tests/test_synchdata.cpp new file mode 100644 index 00000000..59b43b67 --- /dev/null +++ b/tests/test_synchdata.cpp @@ -0,0 +1,88 @@ +/* Copyright (C) 2003 Scott Wheeler + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +using namespace std; +using namespace TagLib; + +class TestID3v2SynchData : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(TestID3v2SynchData); + CPPUNIT_TEST(test1); + CPPUNIT_TEST(test2); + CPPUNIT_TEST(test3); + CPPUNIT_TEST(testDecode1); + CPPUNIT_TEST(testDecode2); + CPPUNIT_TEST_SUITE_END(); + +public: + + void test1() + { + char data[] = { 0, 0, 0, 127 }; + ByteVector v(data, 4); + + CPPUNIT_ASSERT_EQUAL(ID3v2::SynchData::toUInt(v), TagLib::uint(127)); + CPPUNIT_ASSERT_EQUAL(ID3v2::SynchData::fromUInt(127), v); + } + + void test2() + { + char data[] = { 0, 0, 1, 0 }; + ByteVector v(data, 4); + + CPPUNIT_ASSERT_EQUAL(ID3v2::SynchData::toUInt(v), TagLib::uint(128)); + CPPUNIT_ASSERT_EQUAL(ID3v2::SynchData::fromUInt(128), v); + } + + void test3() + { + char data[] = { 0, 0, 1, 1 }; + ByteVector v(data, 4); + + CPPUNIT_ASSERT_EQUAL(ID3v2::SynchData::toUInt(v), TagLib::uint(129)); + CPPUNIT_ASSERT_EQUAL(ID3v2::SynchData::fromUInt(129), v); + } + + void testDecode1() + { + ByteVector a("\xff\x00\x00", 3); + ID3v2::SynchData::decode(a); + CPPUNIT_ASSERT_EQUAL((unsigned int)2, a.size()); + CPPUNIT_ASSERT_EQUAL(ByteVector("\xff\x00", 2), a); + } + + void testDecode2() + { + ByteVector a("\xff\x44", 2); + ID3v2::SynchData::decode(a); + CPPUNIT_ASSERT_EQUAL((unsigned int)2, a.size()); + CPPUNIT_ASSERT_EQUAL(ByteVector("\xff\x44", 2), a); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v2SynchData); diff --git a/tests/toolkit-test.cpp b/tests/toolkit-test.cpp deleted file mode 100644 index 372c75d6..00000000 --- a/tests/toolkit-test.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright (C) 2003 Scott Wheeler - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include - -using namespace TagLib; -using namespace std; - -void testString(); -void testByteVector(); -void testSynchData(); -void testList(); - -static int resultCount = 1; - -int main() -{ - testString(); - resultCount = 1; - testByteVector(); - resultCount = 1; - testSynchData(); - resultCount = 1; - testList(); - - return 0; -} - -void printResult(bool result) -{ - if(result) - cout << "(" << resultCount << ")\tpass" << endl; - else - cout << "(" << resultCount << ")\tFAIL" << endl; - - resultCount++; -} - -void testString() -{ - cout << "*** Testing TagLib::String ***" << endl; - - String s = "taglib string"; - ByteVector v = "taglib string"; - printResult(v == s.data(String::Latin1)); - - char str[] = "taglib string"; - printResult(strcmp(s.toCString(), str) == 0); - - String unicode("José Carlos", String::UTF8); - printResult(strcmp(unicode.toCString(), "José Carlos") == 0); - - String latin = "José Carlos"; - printResult(strcmp(latin.toCString(true), "José Carlos") == 0); - - String unicode2(unicode.to8Bit(true), String::UTF8); - printResult(unicode == unicode2); - - printResult(strcmp(String::number(0).toCString(), "0") == 0); - printResult(strcmp(String::number(12345678).toCString(), "12345678") == 0); - printResult(strcmp(String::number(-12345678).toCString(), "-12345678") == 0); - - String n = "123"; - printResult(n.toInt() == 123); - - n = "-123"; - printResult(n.toInt() == -123); - - printResult(String("0").toInt() == 0); - printResult(String("1").toInt() == 1); - - printResult(String(" foo ").stripWhiteSpace() == String("foo")); - printResult(String("foo ").stripWhiteSpace() == String("foo")); - printResult(String(" foo").stripWhiteSpace() == String("foo")); - - printResult(memcmp(String("foo").data(String::Latin1).data(), "foo", 3) == 0); - printResult(memcmp(String("f").data(String::Latin1).data(), "f", 1) == 0); - - ByteVector utf16 = unicode.data(String::UTF16); - - // Check to make sure that the BOM is there and that the data size is correct - - printResult(utf16.size() == 2 + (unicode.size() * 2)); - - printResult(unicode == String(utf16, String::UTF16)); -} - -void testConversion(unsigned int i, unsigned char a, unsigned char b, unsigned char c, unsigned char d) -{ - ByteVector v(4, 0); - - v[3] = a; - v[2] = b; - v[1] = c; - v[0] = d; - printResult(v.toUInt(false) == i); - - v[0] = a; - v[1] = b; - v[2] = c; - v[3] = d; - printResult(v.toUInt() == i); -} - - -void testByteVector() -{ - cout << "*** Testing TagLib::ByteVector ***" << endl; - ByteVector v("foobar"); - - printResult(v.find("ob") == 2); - printResult(v.find('b') == 3); - - ByteVector n(4, 0); - n[0] = 1; - printResult(n.toUInt(true) == 16777216); - printResult(n.toUInt(false) == 1); - printResult(ByteVector::fromUInt(16777216, true) == n); - printResult(ByteVector::fromUInt(1, false) == n); - - printResult(ByteVector::fromUInt(0xa0).toUInt() == 0xa0); - - testConversion(0x000000a0, 0x00, 0x00, 0x00, 0xa0); - testConversion(0xd50bf072, 0xd5, 0x0b, 0xf0, 0x72); - - ByteVector intVector(2, 0); - intVector[0] = char(0xfc); - intVector[1] = char(0x00); - printResult(intVector.toShort() == -1024); - intVector[0] = char(0x04); - intVector[1] = char(0x00); - printResult(intVector.toShort() == 1024); - - ByteVector r0("**************"); - ByteVector r1("OggS**********"); - ByteVector r2("**********OggS"); - ByteVector r3("OggS******OggS"); - ByteVector r4("OggS*OggS*OggS"); - - printResult(r0.find("OggS") == -1); - printResult(r0.rfind("OggS") == -1); - printResult(r1.find("OggS") == r1.rfind("OggS")); - printResult(r2.find("OggS") == r2.rfind("OggS")); - printResult(r3.find("OggS") == 0); - printResult(r3.rfind("OggS") == 10); - printResult(r4.rfind("OggS") == 10); - printResult(r4.rfind("OggS", 12) == 5); - - printResult(ByteVector::fromLongLong(1).toLongLong() == 1); - printResult(ByteVector::fromLongLong(0).toLongLong() == 0); - printResult(ByteVector::fromLongLong(0xffffffffffffffffLL).toLongLong() == -1); - printResult(ByteVector::fromLongLong(0xfffffffffffffffeLL).toLongLong() == -2); - printResult(ByteVector::fromLongLong(1024).toLongLong() == 1024); - - ByteVector a1("foo"); - a1.append("bar"); - printResult(a1 == "foobar"); - - ByteVector a2("foo"); - a2.append("b"); - printResult(a2 == "foob"); - - ByteVector a3; - a3.append("b"); - printResult(a3 == "b"); - - ByteVector s1("foo"); - printResult(ByteVectorList::split(s1, " ").size() == 1); - - ByteVector s2("f"); - printResult(ByteVectorList::split(s2, " ").size() == 1); - - - printResult(ByteVector().size() == 0); - printResult(ByteVector("asdf").clear().size() == 0); - printResult(ByteVector("asdf").clear() == ByteVector()); -} - -void testSynchData() -{ - cout << "*** Testing TagLib::ID3v2::SynchData ***" << endl; - - { // test 1 - char data[] = { 0, 0, 0, 127 }; - ByteVector v(data, 4); - - printResult(ID3v2::SynchData::toUInt(v) == 127); - printResult(ID3v2::SynchData::fromUInt(127) == v); - } - { // test 2 - char data[] = { 0, 0, 1, 0 }; - ByteVector v(data, 4); - - printResult(ID3v2::SynchData::toUInt(v) == 128); - printResult(ID3v2::SynchData::fromUInt(128) == v); - } - { // test 3 - char data[] = { 0, 0, 1, 1 }; - ByteVector v(data, 4); - - printResult(ID3v2::SynchData::toUInt(v) == 129); - printResult(ID3v2::SynchData::fromUInt(129) == v); - } -} - -void testList() -{ - cout << "*** Testing TagLib::List ***" << endl; - List l1; - List l2; - List l3; - l1.append(2); - l2.append(3); - l2.append(4); - l1.append(l2); - l1.prepend(1); - l3.append(1); - l3.append(2); - l3.append(3); - l3.append(4); - printResult(l1 == l3); -} diff --git a/tests/utils.h b/tests/utils.h new file mode 100644 index 00000000..21d94526 --- /dev/null +++ b/tests/utils.h @@ -0,0 +1,25 @@ +#include +#include +#include + +using namespace std; + +inline string copyFile(const string &filename, const string &ext) +{ + string newname = string(tempnam(NULL, NULL)) + ext; + string oldname = string("data/") + filename + ext; + char buffer[4096]; + int bytes; + int inf = open(oldname.c_str(), O_RDONLY); + int outf = open(newname.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); + while((bytes = read(inf, buffer, sizeof(buffer))) > 0) + write(outf, buffer, bytes); + close(outf); + close(inf); + return newname; +} + +inline void deleteFile(const string &filename) +{ + remove(filename.c_str()); +}