From deab4627356af870453f5f71c501ff27643b473f Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Thu, 15 Jul 2004 16:22:43 +0000 Subject: [PATCH] add libFLAC++ equivalent callback-based chain reading/writing and tests --- include/FLAC++/metadata.h | 6 + src/libFLAC++/metadata.cpp | 24 ++ src/test_libFLAC++/metadata_manip.cpp | 406 ++++++++++++++++++++++++-- 3 files changed, 416 insertions(+), 20 deletions(-) diff --git a/include/FLAC++/metadata.h b/include/FLAC++/metadata.h index 8a2d0823..500b5b16 100644 --- a/include/FLAC++/metadata.h +++ b/include/FLAC++/metadata.h @@ -908,7 +908,13 @@ namespace FLAC { Status status(); bool read(const char *filename); + bool read(FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); + + bool check_if_tempfile_needed(bool use_padding); + bool write(bool use_padding = true, bool preserve_file_stats = false); + bool write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks); + bool write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks); void merge_padding(); void sort_padding(); diff --git a/src/libFLAC++/metadata.cpp b/src/libFLAC++/metadata.cpp index f71fb661..fd6e763e 100644 --- a/src/libFLAC++/metadata.cpp +++ b/src/libFLAC++/metadata.cpp @@ -1122,12 +1122,36 @@ namespace FLAC { return (bool)::FLAC__metadata_chain_read(chain_, filename); } + bool Chain::read(FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__metadata_chain_read_with_callbacks(chain_, handle, callbacks); + } + + bool Chain::check_if_tempfile_needed(bool use_padding) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__metadata_chain_check_if_tempfile_needed(chain_, use_padding); + } + bool Chain::write(bool use_padding, bool preserve_file_stats) { FLAC__ASSERT(is_valid()); return (bool)::FLAC__metadata_chain_write(chain_, use_padding, preserve_file_stats); } + bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__metadata_chain_write_with_callbacks(chain_, use_padding, handle, callbacks); + } + + bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain_, use_padding, handle, callbacks, temp_handle, temp_callbacks); + } + void Chain::merge_padding() { FLAC__ASSERT(is_valid()); diff --git a/src/test_libFLAC++/metadata_manip.cpp b/src/test_libFLAC++/metadata_manip.cpp index e8922630..7720d4d2 100644 --- a/src/test_libFLAC++/metadata_manip.cpp +++ b/src/test_libFLAC++/metadata_manip.cpp @@ -27,6 +27,16 @@ extern "C" { #include /* for malloc() */ #include /* for memcpy()/memset() */ +#if defined _MSC_VER || defined __MINGW32__ +#include /* for utime() */ +#include /* for chmod() */ +#else +#include /* some flavors of BSD (like OS X) require this to get time_t */ +#include /* for utime() */ +#include /* for chown(), unlink() */ +#endif +#include /* for stat(), maybe chmod() */ + /****************************************************************************** The general strategy of these tests (for interface levels 1 and 2) is to create a dummy FLAC file with a known set of initial metadata @@ -166,6 +176,202 @@ void add_to_padding_length_(unsigned index, int delta) padding->set_length((unsigned)((int)padding->get_length() + delta)); } +/* + * This wad of functions supports filename- and callback-based chain reading/writing. + * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c + */ +bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename) +{ + static const char *tempfile_suffix = ".metadata_edit"; + + if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1))) + return false; + strcpy(*tempfilename, filename); + strcat(*tempfilename, tempfile_suffix); + + if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) + return false; + + return true; +} + +void cleanup_tempfile_(FILE **tempfile, char **tempfilename) +{ + if(0 != *tempfile) { + (void)fclose(*tempfile); + *tempfile = 0; + } + + if(0 != *tempfilename) { + (void)unlink(*tempfilename); + free(*tempfilename); + *tempfilename = 0; + } +} + +bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != tempfile); + FLAC__ASSERT(0 != tempfilename); + FLAC__ASSERT(0 != *tempfilename); + + if(0 != *tempfile) { + (void)fclose(*tempfile); + *tempfile = 0; + } + +#if defined _MSC_VER || defined __MINGW32__ + if(unlink(filename) < 0) { + cleanup_tempfile_(tempfile, tempfilename); + return false; + } +#endif + + if(0 != rename(*tempfilename, filename)) { + cleanup_tempfile_(tempfile, tempfilename); + return false; + } + + cleanup_tempfile_(tempfile, tempfilename); + + return true; +} + +bool get_file_stats_(const char *filename, struct stat *stats) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != stats); + return (0 == stat(filename, stats)); +} + +void set_file_stats_(const char *filename, struct stat *stats) +{ + struct utimbuf srctime; + + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != stats); + + srctime.actime = stats->st_atime; + srctime.modtime = stats->st_mtime; + (void)chmod(filename, stats->st_mode); + (void)utime(filename, &srctime); +#if !defined _MSC_VER && !defined __MINGW32__ + (void)chown(filename, stats->st_uid, (gid_t)(-1)); + (void)chown(filename, (uid_t)(-1), stats->st_gid); +#endif +} + +#ifdef FLAC__VALGRIND_TESTING +static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, ::FLAC__IOHandle handle) +{ + FILE *stream = (FILE*)handle; + size_t ret = fwrite(ptr, size, nmemb, stream); + if(!ferror(stream)) + fflush(stream); + return ret; +} +#endif + +static int chain_seek_cb_(::FLAC__IOHandle handle, FLAC__int64 offset, int whence) +{ + long o = (long)offset; + FLAC__ASSERT(offset == o); + return fseek((FILE*)handle, o, whence); +} + +static FLAC__int64 chain_tell_cb_(::FLAC__IOHandle handle) +{ + return ftell((FILE*)handle); +} + +static int chain_eof_cb_(::FLAC__IOHandle handle) +{ + return feof((FILE*)handle); +} + +static bool write_chain_(FLAC::Metadata::Chain &chain, bool use_padding, bool preserve_file_stats, bool filename_based, const char *filename) +{ + if(filename_based) + return chain.write(use_padding, preserve_file_stats); + else { + ::FLAC__IOCallbacks callbacks; + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.read = (::FLAC__IOCallback_Read)fread; +#ifdef FLAC__VALGRIND_TESTING + callbacks.write = chain_write_cb_; +#else + callbacks.write = (::FLAC__IOCallback_Write)fwrite; +#endif + callbacks.seek = chain_seek_cb_; + callbacks.eof = chain_eof_cb_; + + if(chain.check_if_tempfile_needed(use_padding)) { + struct stat stats; + FILE *file, *tempfile; + char *tempfilename; + if(preserve_file_stats) { + if(!get_file_stats_(filename, &stats)) + return false; + } + if(0 == (file = fopen(filename, "rb"))) + return false; /*@@@ chain status still says OK though */ + if(!open_tempfile_(filename, &tempfile, &tempfilename)) { + fclose(file); + cleanup_tempfile_(&tempfile, &tempfilename); + return false; /*@@@ chain status still says OK though */ + } + if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks, (::FLAC__IOHandle)tempfile, callbacks)) { + fclose(file); + fclose(tempfile); + return false; + } + fclose(file); + fclose(tempfile); + file = tempfile = 0; + if(!transport_tempfile_(filename, &tempfile, &tempfilename)) + return false; + if(preserve_file_stats) + set_file_stats_(filename, &stats); + } + else { + FILE *file = fopen(filename, "r+b"); + if(0 == file) + return false; /*@@@ chain status still says OK though */ + if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks)) + return false; + fclose(file); + } + } + + return true; +} + +static bool read_chain_(FLAC::Metadata::Chain &chain, const char *filename, bool filename_based) +{ + if(filename_based) + return chain.read(filename); + else { + ::FLAC__IOCallbacks callbacks; + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.read = (::FLAC__IOCallback_Read)fread; + callbacks.seek = chain_seek_cb_; + callbacks.tell = chain_tell_cb_; + + { + bool ret; + FILE *file = fopen(filename, "rb"); + if(0 == file) + return false; /*@@@ chain status still says OK though */ + ret = chain.read((::FLAC__IOHandle)file, callbacks); + fclose(file); + return ret; + } + } +} + /* function for comparing our metadata to a FLAC::Metadata::Chain */ static bool compare_chain_(FLAC::Metadata::Chain &chain, unsigned current_position, FLAC::Metadata::Prototype *current_block) @@ -1082,7 +1288,7 @@ static bool test_level_1_() return true; } -static bool test_level_2_() +static bool test_level_2_(bool filename_based) { FLAC::Metadata::Prototype *block; FLAC::Metadata::StreamInfo *streaminfo; @@ -1094,7 +1300,7 @@ static bool test_level_2_() // initialize 'data' to avoid Valgrind errors memset(data, 0, sizeof(data)); - printf("\n\n++++++ testing level 2 interface\n"); + printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback"); printf("generate read-only file\n"); @@ -1111,7 +1317,7 @@ static bool test_level_2_() printf("read chain\n"); - if(!chain.read(flacfile_)) + if(!read_chain_(chain, flacfile_, filename_based)) return die_c_("reading chain", chain.status()); printf("[S]VP\ttest initial metadata\n"); @@ -1150,7 +1356,7 @@ static bool test_level_2_() return die_("copying object"); delete block; - if(!chain.write(/*use_padding=*/false, /*preserve_file_stats=*/true)) + if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_)) return die_c_("during chain.write(false, true)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1183,7 +1389,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(false, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1202,7 +1408,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(false, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1221,7 +1427,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(false, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1240,7 +1446,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(false, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1259,7 +1465,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1283,7 +1489,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1303,7 +1509,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1322,7 +1528,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1342,7 +1548,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1362,7 +1568,7 @@ static bool test_level_2_() if(!iterator.set_block(app)) return die_c_("iterator.set_block(app)", chain.status()); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); block = iterator.get_block(); if(!compare_chain_(chain, our_current_position, block)) @@ -1489,7 +1695,7 @@ static bool test_level_2_() delete_from_our_metadata_(4); delete_from_our_metadata_(3); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); if(!compare_chain_(chain, 0, 0)) return false; @@ -1501,7 +1707,7 @@ static bool test_level_2_() add_to_padding_length_(4, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->get_length()); delete_from_our_metadata_(2); - if(!chain.write(/*use_padding=*/true, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(true, false)", chain.status()); if(!compare_chain_(chain, 0, 0)) return false; @@ -1605,13 +1811,13 @@ static bool test_level_2_() return false; delete block; - } + } // delete iterator our_current_position = 0; printf("SV\tmerge padding\n"); chain.merge_padding(); - if(!chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(false, false)", chain.status()); if(!compare_chain_(chain, 0, 0)) return false; @@ -1621,7 +1827,7 @@ static bool test_level_2_() printf("SV\tsort padding\n"); chain.sort_padding(); - if(!chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false)) + if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_)) return die_c_("during chain.write(false, false)", chain.status()); if(!compare_chain_(chain, 0, 0)) return false; @@ -1634,6 +1840,162 @@ static bool test_level_2_() return true; } +static bool test_level_2_misc_() +{ + ::FLAC__IOCallbacks callbacks; + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.read = (::FLAC__IOCallback_Read)fread; +#ifdef FLAC__VALGRIND_TESTING + callbacks.write = chain_write_cb_; +#else + callbacks.write = (::FLAC__IOCallback_Write)fwrite; +#endif + callbacks.seek = chain_seek_cb_; + callbacks.tell = chain_tell_cb_; + callbacks.eof = chain_eof_cb_; + + printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n"); + + printf("generate file\n"); + + if(!generate_file_()) + return false; + + printf("create chain\n"); + FLAC::Metadata::Chain chain; + if(!chain.is_valid()) + return die_("allocating chain"); + + printf("read chain (filename-based)\n"); + + if(!chain.read(flacfile_)) + return die_c_("reading chain", chain.status()); + + printf("write chain with wrong method Chain::write(with callbacks)\n"); + { + if(chain.write(/*use_padding=*/false, 0, callbacks)) + return die_c_("mismatched write should have failed", chain.status()); + if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH) + return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status()); + printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n"); + } + + printf("read chain (filename-based)\n"); + + if(!chain.read(flacfile_)) + return die_c_("reading chain", chain.status()); + + printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n"); + { + if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks)) + return die_c_("mismatched write should have failed", chain.status()); + if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH) + return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status()); + printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n"); + } + + printf("read chain (callback-based)\n"); + { + FILE *file = fopen(flacfile_, "rb"); + if(0 == file) + return die_("opening file"); + if(!chain.read((::FLAC__IOHandle)file, callbacks)) { + fclose(file); + return die_c_("reading chain", chain.status()); + } + fclose(file); + } + + printf("write chain with wrong method write()\n"); + { + if(chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false)) + return die_c_("mismatched write should have failed", chain.status()); + if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH) + return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status()); + printf(" OK: write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n"); + } + + printf("read chain (callback-based)\n"); + { + FILE *file = fopen(flacfile_, "rb"); + if(0 == file) + return die_("opening file"); + if(!chain.read((::FLAC__IOHandle)file, callbacks)) { + fclose(file); + return die_c_("reading chain", chain.status()); + } + fclose(file); + } + + printf("testing Chain::check_if_tempfile_needed()... "); + + if(!chain.check_if_tempfile_needed(/*use_padding=*/false)) + printf("OK: Chain::check_if_tempfile_needed() returned false like it should\n"); + else + return die_("Chain::check_if_tempfile_needed() returned true but shouldn't have"); + + printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n"); + { + if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks)) + return die_c_("mismatched write should have failed", chain.status()); + if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL) + return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status()); + printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n"); + } + + printf("read chain (callback-based)\n"); + { + FILE *file = fopen(flacfile_, "rb"); + if(0 == file) + return die_("opening file"); + if(!chain.read((::FLAC__IOHandle)file, callbacks)) { + fclose(file); + return die_c_("reading chain", chain.status()); + } + fclose(file); + } + + printf("create iterator\n"); + { + FLAC::Metadata::Iterator iterator; + if(!iterator.is_valid()) + return die_("allocating memory for iterator"); + + iterator.init(chain); + + printf("[S]VP\tnext\n"); + if(!iterator.next()) + return die_("iterator ended early\n"); + + printf("S[V]P\tdelete VORBIS_COMMENT, write\n"); + if(!iterator.delete_block(/*replace_with_padding=*/false)) + return die_c_("block delete failed\n", chain.status()); + + printf("testing Chain::check_if_tempfile_needed()... "); + + if(chain.check_if_tempfile_needed(/*use_padding=*/false)) + printf("OK: Chain::check_if_tempfile_needed() returned true like it should\n"); + else + return die_("Chain::check_if_tempfile_needed() returned false but shouldn't have"); + + printf("write chain with wrong method Chain::write(with callbacks)\n"); + { + if(chain.write(/*use_padding=*/false, 0, callbacks)) + return die_c_("mismatched write should have failed", chain.status()); + if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL) + return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status()); + printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n"); + } + + } // delete iterator + + if(!remove_file_(flacfile_)) + return false; + + return true; +} + bool test_metadata_file_manipulation() { printf("\n+++ libFLAC++ unit test: metadata manipulation\n\n"); @@ -1646,7 +2008,11 @@ bool test_metadata_file_manipulation() if(!test_level_1_()) return false; - if(!test_level_2_()) + if(!test_level_2_(/*filename_based=*/true)) /* filename-based */ + return false; + if(!test_level_2_(/*filename_based=*/false)) /* callback-based */ + return false; + if(!test_level_2_misc_()) return false; return true;