diff --git a/src/opustags.h b/src/opustags.h index 6570a3c..b91a836 100644 --- a/src/opustags.h +++ b/src/opustags.h @@ -84,6 +84,18 @@ struct status { std::string message; }; +/** + * Call a fopen-like function that returns a FILE* such that the returned pointer is smart and calls + * fclose on destruction. + * + * Example : `auto my_file = ot::make_file(fopen, "foo.txt", "r");` + */ +template +std::unique_ptr make_file(Opener&& f, Args&&... args) +{ + return {f(std::forward(args)...), &fclose}; +} + /***********************************************************************************************//** * \defgroup ogg Ogg * \{ diff --git a/t/CMakeLists.txt b/t/CMakeLists.txt index 6f046df..365b228 100644 --- a/t/CMakeLists.txt +++ b/t/CMakeLists.txt @@ -4,10 +4,13 @@ target_link_libraries(opus.t libopustags) add_executable(ogg.t EXCLUDE_FROM_ALL ogg.cc) target_link_libraries(ogg.t libopustags) +add_executable(cli.t EXCLUDE_FROM_ALL cli.cc) +target_link_libraries(cli.t libopustags) + configure_file(gobble.opus . COPYONLY) add_custom_target( check COMMAND prove "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" - DEPENDS opustags gobble.opus opus.t ogg.t + DEPENDS opustags gobble.opus opus.t ogg.t cli.t ) diff --git a/t/cli.cc b/t/cli.cc new file mode 100644 index 0000000..74bd4d4 --- /dev/null +++ b/t/cli.cc @@ -0,0 +1,25 @@ +#include +#include "tap.h" + +const char *user_comments = R"raw( +TITLE=a b c + +ARTIST=X +Artist=Y +)raw"; + +void check_read_comments() +{ + auto input = ot::make_file(fmemopen, const_cast(user_comments), strlen(user_comments), "r"); + auto comments = ot::read_comments(input.get()); + auto&& expected = {"TITLE=a b c", "ARTIST=X", "Artist=Y"}; + if (!std::equal(comments.begin(), comments.end(), expected.begin(), expected.end())) + throw failure("parsed user comments did not match expectations"); +} + +int main(int argc, char **argv) +{ + std::cout << "1..1\n"; + run(check_read_comments, "check tags parsing"); + return 0; +}