2016-07-30 23:17:49 +02:00
# include <c++utilities/conversion/stringconversion.h>
2016-08-03 17:48:53 +02:00
# include <c++utilities/io/catchiofailure.h>
2016-07-30 23:17:49 +02:00
# include <c++utilities/tests/testutils.h>
2016-08-03 17:48:53 +02:00
# include <tagparser/mediafileinfo.h>
2016-07-30 23:17:49 +02:00
# include <cppunit/extensions/HelperMacros.h>
# include <cppunit/TestFixture.h>
# include <iostream>
2016-08-03 17:48:53 +02:00
# include <fstream>
2016-07-30 23:17:49 +02:00
using namespace std ;
using namespace TestUtilities ;
2016-08-03 17:48:53 +02:00
using namespace ConversionUtilities ;
using namespace Media ;
2016-07-30 23:17:49 +02:00
using namespace CPPUNIT_NS ;
enum class TagStatus
{
Original ,
TestMetaDataPresent ,
Removed
} ;
/*!
* \ brief The CliTests class tests the command line interface .
*/
class CliTests : public TestFixture
{
CPPUNIT_TEST_SUITE ( CliTests ) ;
# ifdef PLATFORM_UNIX
CPPUNIT_TEST ( testBasicReadingAndWriting ) ;
CPPUNIT_TEST ( testHandlingOfTargets ) ;
CPPUNIT_TEST ( testHandlingOfId3Tags ) ;
CPPUNIT_TEST ( testMultipleFiles ) ;
CPPUNIT_TEST ( testMultipleValuesPerField ) ;
CPPUNIT_TEST ( testHandlingAttachments ) ;
2016-07-31 23:22:22 +02:00
CPPUNIT_TEST ( testDisplayingInfo ) ;
CPPUNIT_TEST ( testExtraction ) ;
CPPUNIT_TEST ( testReadingAndWritingDocumentTitle ) ;
2016-07-30 23:17:49 +02:00
# endif
CPPUNIT_TEST_SUITE_END ( ) ;
public :
void setUp ( ) ;
void tearDown ( ) ;
# ifdef PLATFORM_UNIX
void testBasicReadingAndWriting ( ) ;
void testHandlingOfTargets ( ) ;
void testHandlingOfId3Tags ( ) ;
void testMultipleFiles ( ) ;
void testMultipleValuesPerField ( ) ;
void testHandlingAttachments ( ) ;
2016-07-31 23:22:22 +02:00
void testDisplayingInfo ( ) ;
void testExtraction ( ) ;
void testReadingAndWritingDocumentTitle ( ) ;
2016-07-30 23:17:49 +02:00
# endif
private :
} ;
CPPUNIT_TEST_SUITE_REGISTRATION ( CliTests ) ;
void CliTests : : setUp ( )
{ }
void CliTests : : tearDown ( )
{ }
# ifdef PLATFORM_UNIX
/*!
* \ brief Tests basic reading and writing of tags .
*/
void CliTests : : testBasicReadingAndWriting ( )
{
string stdout , stderr ;
// get specific field
2016-07-31 23:22:22 +02:00
const string mkvFile ( workingCopyPath ( " matroska_wave1/test2.mkv " ) ) ;
2016-08-03 17:48:53 +02:00
const string mkvFileBackup ( mkvFile + " .bak " ) ;
2016-07-30 23:17:49 +02:00
const char * const args1 [ ] = { " tageditor " , " get " , " title " , " -f " , mkvFile . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
CPPUNIT_ASSERT ( stderr . empty ( ) ) ;
// context of the following fields is the album (so "Title" means the title of the album)
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" album " ,
" Title Elephant Dream - test 2 "
} ) ) ;
2016-07-30 23:17:49 +02:00
CPPUNIT_ASSERT ( stdout . find ( " Year 2010 " ) = = string : : npos ) ;
// get all fields
const char * const args2 [ ] = { " tageditor " , " get " , " -f " , mkvFile . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
CPPUNIT_ASSERT ( stderr . empty ( ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Title Elephant Dream - test 2 " ,
" Year 2010 " ,
" Comment Matroska Validation File 2, 100,000 timecode scale, odd aspect ratio, and CRC-32. Codecs are AVC and AAC "
} ) ) ;
2016-07-30 23:17:49 +02:00
// set some fields, keep other field
const char * const args3 [ ] = { " tageditor " , " set " , " title=A new title " , " genre=Testfile " , " -f " , mkvFile . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args3 , stdout , stderr ) ) ;
CPPUNIT_ASSERT ( stdout . find ( " Changes have been applied " ) ! = string : : npos ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
CPPUNIT_ASSERT ( stderr . empty ( ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Title A new title " ,
" Genre Testfile " ,
" Year 2010 " ,
" Comment Matroska Validation File 2, 100,000 timecode scale, odd aspect ratio, and CRC-32. Codecs are AVC and AAC "
} ) ) ;
// clear backup file
remove ( mkvFileBackup . data ( ) ) ;
2016-07-30 23:17:49 +02:00
// set some fields, discard other
const char * const args4 [ ] = { " tageditor " , " set " , " title=Foo " , " artist=Bar " , " --remove-other-fields " , " -f " , mkvFile . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args4 , stdout , stderr ) ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
CPPUNIT_ASSERT ( stderr . empty ( ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Title Foo " ,
" Artist Bar "
} ) ) ;
2016-07-30 23:17:49 +02:00
CPPUNIT_ASSERT ( stdout . find ( " Year " ) = = string : : npos ) ;
CPPUNIT_ASSERT ( stdout . find ( " Comment " ) = = string : : npos ) ;
CPPUNIT_ASSERT ( stdout . find ( " Genre " ) = = string : : npos ) ;
2016-08-03 17:48:53 +02:00
// clear working copies if all tests have been
remove ( mkvFile . c_str ( ) ) ;
remove ( mkvFileBackup . data ( ) ) ;
2016-07-30 23:17:49 +02:00
}
/*!
* \ brief Tests adding and removing of targets .
*/
void CliTests : : testHandlingOfTargets ( )
{
string stdout , stderr ;
2016-07-31 23:22:22 +02:00
const string mkvFile ( workingCopyPath ( " matroska_wave1/test2.mkv " ) ) ;
2016-08-03 17:48:53 +02:00
const string mkvFileBackup ( mkvFile + " .bak " ) ;
2016-07-30 23:17:49 +02:00
const char * const args1 [ ] = { " tageditor " , " get " , " -f " , mkvFile . data ( ) , nullptr } ;
// add song title (title field for tag with level 30)
const char * const args2 [ ] = { " tageditor " , " set " , " target-level=30 " , " title=The song title " , " genre=The song genre " , " target-level=50 " , " genre=The album genre " , " -f " , mkvFile . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" song " ,
" Title The song title " ,
" Genre The song genre "
} ) ) ;
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" album " ,
" Title Elephant Dream - test 2 " ,
" Genre The album genre "
} ) ) ;
remove ( mkvFileBackup . data ( ) ) ;
2016-07-30 23:17:49 +02:00
// remove tags targeting level 30 and 50 and add new tag targeting level 30 and the audio track
2016-07-31 23:22:22 +02:00
const char * const args3 [ ] = { " tageditor " , " set " , " target-level=30 " , " target-tracks=3134325680 " , " title=The audio track " , " encoder=likely some AAC encoder " , " --remove-target " , " target-level=30 " , " --remove-target " , " target-level=50 " , " -f " , mkvFile . data ( ) , nullptr } ;
2016-07-30 23:17:49 +02:00
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args3 , stdout , stderr ) ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , { " song " } ) ) ;
CPPUNIT_ASSERT ( ! containsSubstrings ( stdout , { " song " , " song " } ) ) ;
CPPUNIT_ASSERT ( stdout . find ( " album " ) = = string : : npos ) ;
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" 3134325680 " ,
" Title The audio track " ,
" Encoder likely some AAC encoder "
} ) ) ;
remove ( mkvFileBackup . data ( ) ) ;
// clear working copies if all tests have been
remove ( mkvFile . c_str ( ) ) ;
2016-07-30 23:17:49 +02:00
}
/*!
2016-07-31 23:22:22 +02:00
* \ brief Tests handling of ID3v1 and ID3v2 tags and MP3 specific options .
2016-07-30 23:17:49 +02:00
*/
void CliTests : : testHandlingOfId3Tags ( )
{
// TODO
}
/*!
* \ brief Tests reading and writing multiple files at once .
*/
void CliTests : : testMultipleFiles ( )
{
string stdout , stderr ;
2016-07-31 23:22:22 +02:00
const string mkvFile1 ( workingCopyPath ( " matroska_wave1/test1.mkv " ) ) ;
const string mkvFile2 ( workingCopyPath ( " matroska_wave1/test2.mkv " ) ) ;
const string mkvFile3 ( workingCopyPath ( " matroska_wave1/test3.mkv " ) ) ;
2016-07-30 23:17:49 +02:00
// get tags of 3 files at once
const char * const args1 [ ] = { " tageditor " , " get " , " -f " , mkvFile1 . data ( ) , mkvFile2 . data ( ) , mkvFile3 . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Title Big Buck Bunny - test 1 " ,
" Title Elephant Dream - test 2 " ,
" Title Elephant Dream - test 3 "
} ) ) ;
// clear backup files
remove ( ( mkvFile1 + " .bak " ) . c_str ( ) ) , remove ( ( mkvFile2 + " .bak " ) . c_str ( ) ) , remove ( ( mkvFile3 + " .bak " ) . c_str ( ) ) ;
2016-07-30 23:17:49 +02:00
// set title and part number of 3 files at once
const char * const args2 [ ] = { " tageditor " , " set " , " target-level=30 " , " title=test1 " , " title=test2 " , " title=test3 " , " part+=1 " , " target-level=50 " , " title=MKV testfiles " , " totalparts=3 " , " -f " , mkvFile1 . data ( ) , mkvFile2 . data ( ) , mkvFile3 . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Matroska tag targeting \" level 50 'album, opera, concert, movie, episode' \" \n "
" Title MKV testfiles \n "
" Year 2010 \n "
" Comment Matroska Validation File1, basic MPEG4.2 and MP3 with only SimpleBlock \n "
" Total parts 3 \n "
" Matroska tag targeting \" level 30 'track, song, chapter' \" \n "
" Title test1 \n "
" Part 1 " ,
" Matroska tag targeting \" level 50 'album, opera, concert, movie, episode' \" \n "
" Title MKV testfiles \n "
" Year 2010 \n "
" Comment Matroska Validation File 2, 100,000 timecode scale, odd aspect ratio, and CRC-32. Codecs are AVC and AAC \n "
" Total parts 3 \n "
" Matroska tag targeting \" level 30 'track, song, chapter' \" \n "
" Title test2 \n "
" Part 2 " ,
" Matroska tag targeting \" level 50 'album, opera, concert, movie, episode' \" \n "
" Title MKV testfiles \n "
" Year 2010 \n "
" Comment Matroska Validation File 3, header stripping on the video track and no SimpleBlock \n "
" Total parts 3 \n "
" Matroska tag targeting \" level 30 'track, song, chapter' \" \n "
" Title test3 \n "
" Part 3 "
} ) ) ;
// clear working copies if all tests have been
remove ( mkvFile1 . c_str ( ) ) , remove ( mkvFile2 . c_str ( ) ) , remove ( mkvFile3 . c_str ( ) ) ;
remove ( ( mkvFile1 + " .bak " ) . c_str ( ) ) , remove ( ( mkvFile2 + " .bak " ) . c_str ( ) ) , remove ( ( mkvFile3 + " .bak " ) . c_str ( ) ) ;
2016-07-30 23:17:49 +02:00
}
/*!
* \ brief Tests tagging multiple values per field .
2016-08-03 17:48:53 +02:00
* \ remarks Fails because feature has not been implemented yet .
2016-07-30 23:17:49 +02:00
*/
void CliTests : : testMultipleValuesPerField ( )
{
2016-08-03 17:48:53 +02:00
string stdout , stderr ;
const string mkvFile ( workingCopyPath ( " matroska_wave1/test1.mkv " ) ) ;
const char * const args1 [ ] = { " tageditor " , " get " , " -f " , mkvFile . data ( ) , nullptr } ;
const char * const args2 [ ] = { " tageditor " , " set " , " artist=test1 " , " +artist=test2 " , " +artist=test3 " , " -f " , mkvFile . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
//cout << stdout << endl;
//cerr << stderr << endl;
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Artist test1 " ,
" Artist test2 " ,
" Artist test3 "
} ) ) ;
// clear working copies if all tests have been
remove ( mkvFile . c_str ( ) ) ;
remove ( ( mkvFile + " .bak " ) . c_str ( ) ) ;
2016-07-30 23:17:49 +02:00
}
/*!
* \ brief Tests handling attachments .
*/
void CliTests : : testHandlingAttachments ( )
2016-07-31 23:22:22 +02:00
{
string stdout , stderr ;
const string mkvFile1 ( workingCopyPath ( " matroska_wave1/test1.mkv " ) ) ;
2016-08-03 17:48:53 +02:00
const string mkvFile1Backup ( mkvFile1 + " .bak " ) ;
2016-07-31 23:22:22 +02:00
const string mkvFile2 ( " path= " + testFilePath ( " matroska_wave1/test2.mkv " ) ) ;
// add attachment
const char * const args2 [ ] = { " tageditor " , " set " , " --add-attachment " , " name=test2.mkv " , " mime=video/x-matroska " , " desc=Test attachment " , mkvFile2 . data ( ) , " -f " , mkvFile1 . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
const char * const args1 [ ] = { " tageditor " , " info " , " -f " , mkvFile1 . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Attachments: " ,
" Name test2.mkv " ,
" MIME-type video/x-matroska " ,
" Description Test attachment " ,
" Size 20.16 MiB (21142764 byte) "
} ) ) ;
// clear backup file
remove ( mkvFile1Backup . data ( ) ) ;
2016-07-31 23:22:22 +02:00
// update attachment
const char * const args3 [ ] = { " tageditor " , " set " , " --update-attachment " , " name=test2.mkv " , " desc=Updated test attachment " , " -f " , mkvFile1 . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args3 , stdout , stderr ) ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
2016-08-03 17:48:53 +02:00
CPPUNIT_ASSERT ( containsSubstrings ( stdout , {
" Attachments: " ,
" Name test2.mkv " ,
" MIME-type video/x-matroska " ,
" Description Updated test attachment " ,
" Size 20.16 MiB (21142764 byte) "
} ) ) ;
// clear backup file
remove ( mkvFile1Backup . data ( ) ) ;
// extract assigned attachment again
const char * const args4 [ ] = { " tageditor " , " extract " , " --attachment " , " name=test2.mkv " , " -f " , mkvFile1 . data ( ) , " -o " , " /tmp/extracted.mkv " , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args4 , stdout , stderr ) ) ;
fstream origFile , extFile ;
origFile . exceptions ( ios_base : : failbit | ios_base : : badbit ) , extFile . exceptions ( ios_base : : failbit | ios_base : : badbit ) ;
origFile . open ( mkvFile2 . data ( ) + 5 , ios_base : : in | ios_base : : binary ) , extFile . open ( " /tmp/extracted.mkv " , ios_base : : in | ios_base : : binary ) ;
origFile . seekg ( 0 , ios_base : : end ) , extFile . seekg ( 0 , ios_base : : end ) ;
int64 origFileSize = origFile . tellg ( ) , extFileSize = extFile . tellg ( ) ;
CPPUNIT_ASSERT_EQUAL ( origFileSize , extFileSize ) ;
for ( origFile . seekg ( 0 ) , extFile . seekg ( 0 ) ; origFileSize > 0 ; - - origFileSize ) {
CPPUNIT_ASSERT_EQUAL ( origFile . get ( ) , extFile . get ( ) ) ;
}
remove ( " /tmp/extracted.mkv " ) ;
2016-07-31 23:22:22 +02:00
// remove assigned attachment
const char * const args5 [ ] = { " tageditor " , " set " , " --remove-attachment " , " name=test2.mkv " , " -f " , mkvFile1 . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args5 , stdout , stderr ) ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
CPPUNIT_ASSERT ( stdout . find ( " Attachments: " ) = = string : : npos ) ;
CPPUNIT_ASSERT ( stdout . find ( " Name test2.mkv " ) = = string : : npos ) ;
2016-08-03 17:48:53 +02:00
// clear working copies if all tests have been
remove ( mkvFile1 . data ( ) ) ;
remove ( mkvFile1Backup . data ( ) ) ;
2016-07-31 23:22:22 +02:00
}
/*!
* \ brief Tests displaying general file info .
*/
void CliTests : : testDisplayingInfo ( )
{
// TODO (not very important)
}
/*!
2016-08-03 17:48:53 +02:00
* \ brief Tests extraction of field values ( used to extract cover or other binary fields ) .
* \ remarks Extraction of attachments is already tested in testHandlingAttachments ( ) .
2016-07-31 23:22:22 +02:00
*/
void CliTests : : testExtraction ( )
2016-07-30 23:17:49 +02:00
{
2016-08-03 17:48:53 +02:00
string stdout , stderr ;
const string mp41File ( testFilePath ( " mtx-test-data/alac/othertest-itunes.m4a " ) ) ;
// test extraction of cover
const char * const args1 [ ] = { " tageditor " , " extract " , " cover " , " -f " , mp41File . data ( ) , " -o " , " /tmp/extracted.jpeg " , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args1 , stdout , stderr ) ) ;
MediaFileInfo extractedInfo ( " /tmp/extracted.jpeg " ) ;
extractedInfo . open ( true ) ;
extractedInfo . parseContainerFormat ( ) ;
CPPUNIT_ASSERT_EQUAL ( 22771ul , extractedInfo . size ( ) ) ;
CPPUNIT_ASSERT ( ContainerFormat : : Jpeg = = extractedInfo . containerFormat ( ) ) ;
extractedInfo . invalidate ( ) ;
// test assignment of cover by the way
const string mp4File2 ( workingCopyPath ( " mtx-test-data/aac/he-aacv2-ps.m4a " ) ) ;
const char * const args2 [ ] = { " tageditor " , " set " , " cover=/tmp/extracted.jpeg " , " -f " , mp4File2 . data ( ) , nullptr } ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args2 , stdout , stderr ) ) ;
const char * const args3 [ ] = { " tageditor " , " extract " , " cover " , " -f " , mp4File2 . data ( ) , " -o " , " /tmp/extracted.jpeg " , nullptr } ;
remove ( " /tmp/extracted.jpeg " ) ;
CPPUNIT_ASSERT_EQUAL ( 0 , execApp ( args3 , stdout , stderr ) ) ;
extractedInfo . open ( true ) ;
extractedInfo . parseContainerFormat ( ) ;
CPPUNIT_ASSERT_EQUAL ( 22771ul , extractedInfo . size ( ) ) ;
CPPUNIT_ASSERT ( ContainerFormat : : Jpeg = = extractedInfo . containerFormat ( ) ) ;
remove ( " /tmp/extracted.jpeg " ) ;
remove ( mp4File2 . data ( ) ) ;
remove ( ( mp4File2 + " .bak " ) . data ( ) ) ;
2016-07-30 23:17:49 +02:00
}
/*!
2016-07-31 23:22:22 +02:00
* \ brief Tests reading and writing the document title .
2016-07-30 23:17:49 +02:00
*/
2016-07-31 23:22:22 +02:00
void CliTests : : testReadingAndWritingDocumentTitle ( )
2016-07-30 23:17:49 +02:00
{
// TODO
}
# endif