#define CATCH_CONFIG_MAIN #include "catch.hpp" #include "../filesystem.hpp" #include "../functions.hpp" #include "../resources_linux.h" #include "../tv_rename.hpp" #include "../sqlitepp.hpp" #include #include // declaring functions that aren't in functions.hpp std::string sanitize( const std::string &str ); std::string getDBName(); void cleanUpLine(); std::vector< std::tuple< int, string, string, string > > getRenamedFiles( const string &show, int season, const string &id, const string &language, const string &pattern, const bool &unix_names, const std::map< int, string > &files, bool dvd ); std::map< string, string > getLangs(); // functions required for testing bool authenticated = false; void testDB() { if ( !FSLib::exists( getDBName() ) ) { prepareDB( "S%2seasonE%2episode - %epname" ); } } bool runBash( const std::string &command ) { std::string cmd = "/bin/bash -c \"" + command + "\""; return system( cmd.c_str() ) == 0; } void authenticateTest() { if ( !authenticated ) { authenticate( "42B66F5E-C6BF-423F-ADF9-CC97163472F6" ); authenticated = true; } } // functions.hpp TEST_CASE( "encodeUrl" ) { std::string url1 = "http://google.com"; std::string url1_expected = "http%3A%2F%2Fgoogle.com"; REQUIRE( encodeUrl( url1 ) == url1_expected ); std::string url2 = "https://www.google.com/search?q=日本語"; std::string url2_expected = "https%3A%2F%2Fwww.google.com%2Fsearch%3F" "q%3D%E6%97%A5%E6%9C%AC%E8%AA%9E"; REQUIRE( encodeUrl( url2 ) == url2_expected ); } TEST_CASE( "userHome" ) { SECTION( "correct usage" ) { auto home = userHome(); std::string command = "if [ \"\\${HOME}\" == \""; command += home; command += "\" ] ; then exit 0 ; else exit 1 ; fi"; REQUIRE( runBash( command ) ); } uid_t original_u{ 0 }, original_e{ 0 }, original_s{ 0 }; gid_t original_g{ 0 }, original_ge{ 0 }, original_gs{ 0 }; getresuid( &original_u, &original_e, &original_s ); getresgid( &original_g, &original_ge, &original_gs ); SECTION( "exception with non existing user" ) { setresuid( 1025, 1025, -1 ); REQUIRE_THROWS_WITH( userHome(), Catch::Matchers::Contains( "User with uid" ) && Catch::Matchers::Contains( "doesn't exist!" ) ); } setresuid( original_u, original_e, original_s ); } TEST_CASE( "getlocalized" ) { auto ret = getlocalized( ADDING_TO_DB ); REQUIRE( ret == "Adding to database" ); ret = getlocalized( UPDATING_IN_DB, "test" ); REQUIRE( ret == "Updating test in database" ); } TEST_CASE( "getDBPattern" ) { testDB(); REQUIRE( "S%2seasonE%2episode - %epname" == getDBPattern() ); } TEST_CASE( "searchSeason" ) { size_t seasonpos{ 0 }, eppos{ 0 }; REQUIRE( searchSeason( "s001e003", seasonpos, eppos ) ); REQUIRE( ( seasonpos == 1 && eppos == 5 ) ); REQUIRE( searchSeason( "s001e003", seasonpos ) ); REQUIRE( seasonpos == 1 ); REQUIRE_FALSE( searchSeason( "e01S013", seasonpos, eppos ) ); REQUIRE( searchSeason( "TesTSOIHSADF0239s023S23iewahoiehwf001e22E33sS1E1.mkv", seasonpos, eppos ) ); REQUIRE( ( seasonpos == 45 && eppos == 47 ) ); REQUIRE_FALSE( searchSeason( "s01sE01.mkv", seasonpos ) ); } TEST_CASE( "iterateFS" ) { runBash( "mkdir test_iteratefs ; cd test_iteratefs ; for f in {01..10} ; do " "mkdir \\\"Season \\${f}\\\" ; cd \\\"Season \\${f}\\\" ; for g in " "{01..30} ; do touch \\\"S\\${f}E\\${g}.mkv\\\" ; done ; cd .. ; " "done" ); std::map< int, std::map< int, string > > seasons; iterateFS( seasons, "test_iteratefs" ); REQUIRE( seasons.size() == 10 ); for ( auto &x : seasons ) { REQUIRE( x.second.size() == 30 ); for ( auto &ep : x.second ) { std::string epfile = "S"; if ( x.first <= 9 ) epfile += "0"; epfile += std::to_string( x.first ); epfile += "E"; if ( ep.first <= 9 ) epfile += "0"; epfile += std::to_string( ep.first ); epfile += ".mkv"; REQUIRE_THAT( ep.second, Catch::Contains( epfile ) ); } } REQUIRE_THROWS_WITH( iterateFS( seasons, "nonexistendir" ), Catch::Contains( "Directory" ) && Catch::Contains( "doesn't exist" ) ); REQUIRE_THROWS_WITH( iterateFS( seasons, "test_iteratefs/Season 01/S01E01.mkv" ), Catch::Contains( "Directory" ) && Catch::Contains( "isn't a directory" ) ); } TEST_CASE( "printing functions" ) { std::string expectedHelp = "Usage:\n tv_rename [options] [path]\n\n -h, --help " "show this help message and exit\n\n path can be either a file or a " "directory, if it's a directory\n all files in it and its " "subdirectories will be renamed\n\nOPTIONS\n -s, --show " "TV show from which you want the episode names\n -n, --season " " Season number/s (if multiple seasons,\n " " must be seperated by one space) or 'all'\n " " for all seasons in selected directory\n\n -d, --dvd " " use dvd ordering instead of aired ordering\n --name-pattern " " Pattern to which change the file name.\n --pattern-help " " Print pattern help\n -c, --correct-path This is the " "correct path, stop asking me!\n -t, --trust Don't ask " "whether the names are correct\n -x, --linux Don't " "replace characters characters that are\n " "illegal in Windows\n -l, --lang Select which language " "the episode names shoud be in\n --print-langs Print " "available languages\n\nDATABASE OPTIONS\n --db-add " "Add path to the database\n --db-refresh Refresh " "episode names for all paths in the database\n --db-update " " Check all paths in the database,\n if " "they contain new files, rename them\n --db-name-pattern " "Change name pattern used for files\n " "managed by database\n --db-clean Remove deleted " "files from the database\n --db-remove Remove path " "from the database\n"; std::string expectedPattern = "Possible pattern sequences are:\n %filename - original filename " "(without filetype extension)\n %show - show name from thetvdb\n " "%epname - episode name from thetvdb\n %season - season number\n " "it's possible to specify leading 0 like this:\n %2season (number " "means how many zeros)\n %episode - episode number\n it's possible " "to specify leading 0 like this:\n %2episode (number means how " "many zeros)\nDefault pattern is \"%filename - %epname\"\n"; std::ostringstream oss; auto original_cout = std::cout.rdbuf(); std::cout.rdbuf( oss.rdbuf() ); printHelp(); REQUIRE( oss.str() == expectedHelp ); oss.str( "" ); oss.clear(); printPatternHelp(); REQUIRE( oss.str() == expectedPattern ); std::cout.rdbuf( original_cout ); } TEST_CASE( "parseSeasonNumber" ) { std::set< int > season_nums{}; parseSeasonNumbers( season_nums, "1 2 3 4 5 6" ); REQUIRE( season_nums.size() == 6 ); for ( int i = 1; i < 7; i++ ) { REQUIRE( season_nums.find( i ) != season_nums.end() ); } season_nums.clear(); parseSeasonNumbers( season_nums, "this is not a number" ); REQUIRE( season_nums.size() == 0 ); parseSeasonNumbers( season_nums, "this is not a number 1 2 3 this is the end 4 5 6" ); REQUIRE( season_nums.size() == 3 ); } std::string testCompilePattern( const std::string &pattern ) { return compilePattern( pattern, 45, 914, "episode_of_show_s45e914", "The one where everyone dies", "Enemies" ); } TEST_CASE( "compilePattern" ) { REQUIRE( testCompilePattern( "%filename" ) == "episode_of_show_s45e914" ); REQUIRE( testCompilePattern( "%show" ) == "Enemies" ); REQUIRE( testCompilePattern( "%epname" ) == "The one where everyone dies" ); REQUIRE( testCompilePattern( "%season" ) == "45" ); REQUIRE( testCompilePattern( "%episode" ) == "914" ); REQUIRE( testCompilePattern( "%1season" ) == testCompilePattern( "%2season" ) ); REQUIRE( testCompilePattern( "%20season" ) == "00000000000000000045" ); REQUIRE( testCompilePattern( "%1episode" ) == testCompilePattern( "%2episode" ) ); REQUIRE( testCompilePattern( "%20episode" ) == "00000000000000000914" ); REQUIRE( testCompilePattern( "%filename - %show - S%3seasonE%3episode - %epname" ) == "episode_of_show_s45e914 - Enemies - S045E914 - The one where " "everyone dies" ); REQUIRE( testCompilePattern( "\\%filename" ) == "%filename" ); REQUIRE( testCompilePattern( "\\\\%filename" ) == "\\episode_of_show_s45e914" ); REQUIRE( testCompilePattern( "\\filename" ) == "\\filename" ); REQUIRE( testCompilePattern( "%notakeyword" ) == "%notakeyword" ); } TEST_CASE( "sanitize" ) { REQUIRE( sanitize( "I am a nice input" ) == "I am a nice input" ); REQUIRE( sanitize( "I am an evil input!'; DROP TABLE USER_ACCOUNT_BALANCE;" ) == "I am an evil input!''; DROP TABLE USER_ACCOUNT_BALANCE;" ); } TEST_CASE( "cleanUpLine" ) { std::ostringstream oss; auto original_cout = std::cout.rdbuf(); std::cout.rdbuf( oss.rdbuf() ); cleanUpLine(); std::cout << std::flush; REQUIRE_THAT( oss.str().substr( 3 ), Catch::Contains( "\x1b[2A" ) ); std::cout.rdbuf( original_cout ); } TEST_CASE( "addToDB" ) { testDB(); authenticateTest(); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "1\n" ); runBash( "mkdir add_dir ; touch add_dir/s01e01.mkv" ); std::string show = "simpsons"; addToDB( show, "add_dir", "en", true, false ); SQLite::Database db{}; db.open( getDBName(), SQLite::OPEN_READONLY ); std::vector< std::unordered_map< std::string, std::string > > result_eps{}; std::vector< std::unordered_map< std::string, std::string > > result_shows{}; db.exec( "SELECT * FROM EPISODES;", result_eps ); db.exec( "SELECT * FROM SHOWS;", result_shows ); std::string wanted_id{}; for ( auto &x : result_shows ) { if ( x["SHOW"] == "The Simpsons" ) { wanted_id = x["ID"]; break; } } bool foundCorrect = false; for ( auto &x : result_eps ) { if ( x["PATH"].find( "S01E01 - Simpsons Roasting on an Open Fire.mkv" ) != std::string::npos && x["SHOWID"] == wanted_id ) { foundCorrect = true; break; } } REQUIRE( foundCorrect ); std::cin.rdbuf( original_cin ); std::cout.clear(); } TEST_CASE( "refreshDB" ) { testDB(); authenticateTest(); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "1\n" ); runBash( "mkdir refresh_dir ; touch refresh_dir/s01e01.mkv" ); std::string show = "friends"; addToDB( show, "refresh_dir", "en", true, false ); runBash( "touch refresh_dir/s01e02.mkv" ); refreshDB( true ); SQLite::Database db{}; db.open( getDBName(), SQLite::OPEN_READONLY ); std::vector< std::unordered_map< std::string, std::string > > result_eps{}; std::vector< std::unordered_map< std::string, std::string > > result_shows{}; db.exec( "SELECT * FROM EPISODES;", result_eps ); db.exec( "SELECT * FROM SHOWS;", result_shows ); std::string wanted_id{}; for ( auto &x : result_shows ) { if ( x["SHOW"] == "Friends" ) { wanted_id = x["ID"]; break; } } bool foundCorrect = false; for ( auto &x : result_eps ) { if ( x["PATH"].find( "S01E02 - The One With The Sonogram At The End.mkv" ) != std::string::npos && x["SHOWID"] == wanted_id ) { foundCorrect = true; break; } } REQUIRE( foundCorrect ); std::cin.rdbuf( original_cin ); std::cout.clear(); } TEST_CASE( "updateDB" ) { testDB(); authenticateTest(); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "1\n" ); runBash( "mkdir update_dir ; touch update_dir/s01e01.mkv" ); std::string show = "seinfeld"; addToDB( show, "update_dir", "en", true, false ); runBash( "touch update_dir/s01e02.mkv" ); updateDB( true ); SQLite::Database db{}; db.open( getDBName(), SQLite::OPEN_READONLY ); std::vector< std::unordered_map< std::string, std::string > > result_eps{}; std::vector< std::unordered_map< std::string, std::string > > result_shows{}; db.exec( "SELECT * FROM EPISODES;", result_eps ); db.exec( "SELECT * FROM SHOWS;", result_shows ); std::string wanted_id{}; for ( auto &x : result_shows ) { if ( x["SHOW"] == "Seinfeld" ) { wanted_id = x["ID"]; break; } } bool foundCorrect = false; for ( auto &x : result_eps ) { if ( x["PATH"].find( "S01E02 - The Stake Out.mkv" ) != std::string::npos && x["SHOWID"] == wanted_id ) { foundCorrect = true; break; } } REQUIRE( foundCorrect ); std::cin.rdbuf( original_cin ); std::cout.clear(); } TEST_CASE( "cleanDB" ) { testDB(); authenticateTest(); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "1\n" ); runBash( "mkdir clean_dir ; touch clean_dir/s01e01.mkv" ); std::string show = "scrubs"; addToDB( show, "clean_dir", "en", true, false ); runBash( "rm clean_dir/S01E01*" ); cleanDB(); SQLite::Database db{}; db.open( getDBName(), SQLite::OPEN_READONLY ); std::vector< std::unordered_map< std::string, std::string > > result_eps{}; std::vector< std::unordered_map< std::string, std::string > > result_shows{}; db.exec( "SELECT * FROM EPISODES;", result_eps ); db.exec( "SELECT * FROM SHOWS;", result_shows ); std::string wanted_id{}; for ( auto &x : result_shows ) { if ( x["SHOW"] == "Scrubs" ) { wanted_id = x["ID"]; break; } } bool found = false; for ( auto &x : result_eps ) { if ( x["PATH"].find( "S01E01 - My First Day.mkv" ) != std::string::npos && x["SHOWID"] == wanted_id ) { found = true; break; } } REQUIRE_FALSE( found ); std::cin.rdbuf( original_cin ); std::cout.clear(); } TEST_CASE( "removeFromDB" ) { testDB(); authenticateTest(); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "1\n" ); runBash( "mkdir remove_dir ; touch remove_dir/s01e01.mkv" ); std::string show = "how i met"; addToDB( show, "remove_dir", "en", true, false ); SQLite::Database db{}; db.open( getDBName(), SQLite::OPEN_READONLY ); std::vector< std::unordered_map< std::string, std::string > > result_shows{}; db.exec( "SELECT * FROM SHOWS;", result_shows ); std::string wanted_id{ "0" }; for ( auto &x : result_shows ) { if ( x["SHOW"] == "How I Met Your Mother" ) { wanted_id = x["ID"]; break; } } REQUIRE( wanted_id != "0" ); removeFromDB( FSLib::canonical( "." ) + "/remove_dir" ); wanted_id = "0"; result_shows.clear(); db.exec( "SELECT * FROM SHOWS;", result_shows ); for ( auto &x : result_shows ) { if ( x["SHOW"] == "How I Met Your Mother" ) { wanted_id = x["ID"]; break; } } REQUIRE( wanted_id == "0" ); std::cin.rdbuf( original_cin ); std::cout.clear(); } TEST_CASE( "changeDBPattern" ) { testDB(); std::string old_pattern = "S%2seasonE%2episode - %epname"; std::string new_pattern = "THIS IS NOT A GOOD PATTERN"; REQUIRE( getDBPattern() == old_pattern ); changeDBPattern( new_pattern ); REQUIRE( getDBPattern() == new_pattern ); changeDBPattern( old_pattern ); REQUIRE( getDBPattern() == old_pattern ); } // filesystem.hpp TEST_CASE( "Directory" ) { std::string command = "mkdir test_dir ; cd test_dir ; for f in {01..10} ; do " "touch \\${f} ; done"; runBash( command ); FSLib::Directory d( "test_dir" ); std::set< std::string > files = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10" }; int counter = 0; for ( auto x : d ) { counter++; REQUIRE( files.find( x ) != files.end() ); } REQUIRE( counter == 10 ); } TEST_CASE( "Filesystem" ) { std::string command = "mkdir test_dir2 ; cd test_dir2 ; for f in {01..10} ; do " "touch \\${f} ; done"; runBash( command ); std::set< std::string > files = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10" }; // exists REQUIRE( FSLib::exists( "test_dir2" ) ); for ( auto &x : files ) { REQUIRE( FSLib::exists( "test_dir2/" + x ) ); REQUIRE_FALSE( FSLib::exists( x ) ); } // isDirectory REQUIRE( FSLib::isDirectory( "test_dir2" ) ); REQUIRE( FSLib::isDirectory( "." ) ); REQUIRE_FALSE( FSLib::isDirectory( "test_dir2/01" ) ); REQUIRE_FALSE( FSLib::isDirectory( "nonexistentfile" ) ); // canonical auto pwd = FSLib::canonical( "." ); command = "if [ \"\\${PWD}\" == \""; command += pwd; command += "\" ] ; then exit 0 ; else exit 1 ; fi"; REQUIRE( runBash( command ) ); REQUIRE( FSLib::canonical( "nonexistentfile" ) == "" ); // rename for ( auto &x : files ) { REQUIRE( FSLib::rename( "test_dir2/" + x, "test_dir2/renamed_" + x ) ); REQUIRE_FALSE( FSLib::rename( "test_dir2/" + x, "test_dir2/renamed_" + x ) ); REQUIRE( FSLib::exists( "test_dir2/renamed_" + x ) ); } } // tv_rename.cpp TEST_CASE( "getRenamedFiles Windows chars" ) { std::map< int, std::string > files{}; files[1] = "I am a windows illegal file \\|<>:?\"*"; auto res = getRenamedFiles( "simpsons", 1, "71663", "en", "%filename", false, files, false ); REQUIRE( std::get< 0 >( res[0] ) == 1 ); REQUIRE( std::get< 1 >( res[0] ) == "." ); REQUIRE( std::get< 2 >( res[0] ) == "I am a windows illegal file \\|<>:?\"*" ); REQUIRE( std::get< 3 >( res[0] ) == "I am a windows illegal file -<> - " ); } TEST_CASE( "getLangs" ) { authenticateTest(); auto langs = getLangs(); REQUIRE_FALSE( langs.empty() ); bool containsEn = false; bool containsCs = false; for ( auto &x : langs ) { if ( x.first == "en" ) containsEn = true; if ( x.first == "cs" ) containsCs = true; } REQUIRE( containsEn ); REQUIRE( containsCs ); } TEST_CASE( "singleSeason" ) { runBash( "mkdir test_singleseason ; cd test_singleseason ; for f in {01..10} ;" "do mkdir \\\"Season \\${f}\\\" ; cd \\\"Season \\${f}\\\" ; for g in " "{01..30} ; do touch \\\"S\\${f}E\\${g}.mkv\\\" ; done ; cd .. ; " "done" ); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "y\n" ); singleSeason( "test_singleseason", "simpsons", 1, "71663", "en", "S%2seasonE%2episode - %epname", false, false, nullptr, false, false ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E01 - Simpsons " "Roasting on an Open Fire.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E02 - Bart the Genius.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E03 - Homer's Odyssey.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E04 - There's No " "Disgrace Like Home.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E05 - Bart the General.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E06 - Moaning Lisa.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E07 - The Call of the Simpsons.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E08 - The Telltale Head.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E09 - Life on the Fast Lane.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E10 - Homer's Night Out.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E11 - The Crepes of Wrath.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E12 - Krusty Gets Busted.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 01/S01E13 - Some Enchanted Evening.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 02/S02E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 03/S03E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 04/S04E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 05/S05E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 06/S06E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 07/S07E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 08/S08E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 09/S09E01.mkv" ) ); REQUIRE( FSLib::exists( "test_singleseason/Season 10/S10E01.mkv" ) ); std::cin.rdbuf( original_cin ); std::cout.clear(); } TEST_CASE( "multipleSeasons" ) { runBash( "mkdir test_multipleseasons ; cd test_multipleseasons ;" "for f in {01..10} ; do mkdir \\\"Season \\${f}\\\" ; cd " "\\\"Season \\${f}\\\" ; for g in " "{01..30} ; do touch \\\"S\\${f}E\\${g}.mkv\\\" ; done ; cd .. ; " "done" ); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "1\ny\ny\ny\n" ); multipleSeasons( "test_multipleseasons", "simpsons", { 1, 2, 3 }, "en", "S%2seasonE%2episode - %epname", 0 ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 01/S01E01 - Simpsons " "Roasting on an Open Fire.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 02/S02E01 - Bart Gets an F.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 03/S03E01 - Stark Raving Dad.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 04/S04E01.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 05/S05E01.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 06/S06E01.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 07/S07E01.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 08/S08E01.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 09/S09E01.mkv" ) ); REQUIRE( FSLib::exists( "test_multipleseasons/Season 10/S10E01.mkv" ) ); std::cin.rdbuf( original_cin ); std::cout.clear(); } TEST_CASE( "allSeasons" ) { runBash( "mkdir test_allseasons ; cd test_allseasons ;" "for f in {01..10} ; do mkdir \\\"Season \\${f}\\\" ; cd " "\\\"Season \\${f}\\\" ; for g in " "{01..30} ; do touch \\\"S\\${f}E\\${g}.mkv\\\" ; done ; cd .. ; " "done" ); std::istringstream iss; auto original_cin = std::cin.rdbuf(); std::cin.rdbuf( iss.rdbuf() ); std::cout.setstate( std::ios_base::failbit ); iss.str( "1\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n" ); allSeasons( "test_allseasons", "simpsons", "en", "S%2seasonE%2episode - %epname", 0 ); REQUIRE( FSLib::exists( "test_allseasons/Season 01/S01E01 - Simpsons " "Roasting on an Open Fire.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 02/S02E01 - Bart Gets an F.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 03/S03E01 - Stark Raving Dad.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 04/S04E01 - Kamp Krusty.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 05/S05E01 - Homer's Barbershop Quartet.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 06/S06E01 - Bart of Darkness.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 07/S07E01 - Who Shot Mr. Burns (2).mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 08/S08E01 - Treehouse of Horror VII.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 09/S09E01 - The City of " "New York vs. Homer Simpson.mkv" ) ); REQUIRE( FSLib::exists( "test_allseasons/Season 10/S10E01 - Lard of the Dance.mkv" ) ); std::cin.rdbuf( original_cin ); std::cout.clear(); }