1 /* test_libFLAC++ - Unit tester for libFLAC++
2 * Copyright (C) 2002,2003,2004 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "file_utils.h"
22 #include "FLAC/assert.h"
23 #include "FLAC++/decoder.h"
24 #include "FLAC++/metadata.h"
25 #include "share/grabbag.h"
27 #include <stdlib.h> /* for malloc() */
28 #include <string.h> /* for memcpy()/memset() */
30 #if defined _MSC_VER || defined __MINGW32__
31 #include <sys/utime.h> /* for utime() */
32 #include <io.h> /* for chmod() */
34 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
35 #include <utime.h> /* for utime() */
36 #include <unistd.h> /* for chown(), unlink() */
38 #include <sys/stat.h> /* for stat(), maybe chmod() */
40 /******************************************************************************
41 The general strategy of these tests (for interface levels 1 and 2) is
42 to create a dummy FLAC file with a known set of initial metadata
43 blocks, then keep a mirror locally of what we expect the metadata to be
44 after each operation. Then testing becomes a simple matter of running
45 a FLAC::Decoder::File over the dummy file after each operation, comparing
46 the decoded metadata to what's in our local copy. If there are any
47 differences in the metadata, or the actual audio data is corrupted, we
48 will catch it while decoding.
49 ******************************************************************************/
51 class OurFileDecoder: public FLAC::Decoder::File {
53 inline OurFileDecoder(bool ignore_metadata): ignore_metadata_(ignore_metadata), error_occurred_(false) { }
55 bool ignore_metadata_;
58 ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
59 void metadata_callback(const ::FLAC__StreamMetadata *metadata);
60 void error_callback(::FLAC__StreamDecoderErrorStatus status);
64 FLAC::Metadata::Prototype *blocks[64];
68 static const char *flacfile_ = "metadata.flac";
70 /* our copy of the metadata in flacfile_ */
71 static OurMetadata our_metadata_;
73 /* the current block number that corresponds to the position of the iterator we are testing */
74 static unsigned mc_our_block_number_ = 0;
76 static bool die_(const char *msg)
78 printf("ERROR: %s\n", msg);
82 static bool die_c_(const char *msg, FLAC::Metadata::Chain::Status status)
84 printf("ERROR: %s\n", msg);
85 printf(" status=%u (%s)\n", (unsigned)((::FLAC__Metadata_ChainStatus)status), status.as_cstring());
89 static bool die_ss_(const char *msg, FLAC::Metadata::SimpleIterator &iterator)
91 const FLAC::Metadata::SimpleIterator::Status status = iterator.status();
92 printf("ERROR: %s\n", msg);
93 printf(" status=%u (%s)\n", (unsigned)((::FLAC__Metadata_SimpleIteratorStatus)status), status.as_cstring());
97 static void *malloc_or_die_(size_t size)
99 void *x = malloc(size);
101 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
107 /* functions for working with our metadata copy */
109 static bool replace_in_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
112 FLAC::Metadata::Prototype *obj = block;
113 FLAC__ASSERT(position < our_metadata_.num_blocks);
115 if(0 == (obj = FLAC::Metadata::clone(block)))
116 return die_("during FLAC::Metadata::clone()");
118 delete our_metadata_.blocks[position];
119 our_metadata_.blocks[position] = obj;
121 /* set the is_last flags */
122 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
123 our_metadata_.blocks[i]->set_is_last(false);
124 our_metadata_.blocks[i]->set_is_last(true);
129 static bool insert_to_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
132 FLAC::Metadata::Prototype *obj = block;
134 if(0 == (obj = FLAC::Metadata::clone(block)))
135 return die_("during FLAC::Metadata::clone()");
137 if(position > our_metadata_.num_blocks) {
138 position = our_metadata_.num_blocks;
141 for(i = our_metadata_.num_blocks; i > position; i--)
142 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
144 our_metadata_.blocks[position] = obj;
145 our_metadata_.num_blocks++;
147 /* set the is_last flags */
148 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
149 our_metadata_.blocks[i]->set_is_last(false);
150 our_metadata_.blocks[i]->set_is_last(true);
155 static void delete_from_our_metadata_(unsigned position)
158 FLAC__ASSERT(position < our_metadata_.num_blocks);
159 delete our_metadata_.blocks[position];
160 for(i = position; i < our_metadata_.num_blocks - 1; i++)
161 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
162 our_metadata_.num_blocks--;
164 /* set the is_last flags */
165 if(our_metadata_.num_blocks > 0) {
166 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
167 our_metadata_.blocks[i]->set_is_last(false);
168 our_metadata_.blocks[i]->set_is_last(true);
172 void add_to_padding_length_(unsigned index, int delta)
174 FLAC::Metadata::Padding *padding = dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[index]);
175 FLAC__ASSERT(0 != padding);
176 padding->set_length((unsigned)((int)padding->get_length() + delta));
180 * This wad of functions supports filename- and callback-based chain reading/writing.
181 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
183 bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
185 static const char *tempfile_suffix = ".metadata_edit";
187 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
189 strcpy(*tempfilename, filename);
190 strcat(*tempfilename, tempfile_suffix);
192 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
198 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
201 (void)fclose(*tempfile);
205 if(0 != *tempfilename) {
206 (void)unlink(*tempfilename);
212 bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
214 FLAC__ASSERT(0 != filename);
215 FLAC__ASSERT(0 != tempfile);
216 FLAC__ASSERT(0 != tempfilename);
217 FLAC__ASSERT(0 != *tempfilename);
220 (void)fclose(*tempfile);
224 #if defined _MSC_VER || defined __MINGW32__
225 if(unlink(filename) < 0) {
226 cleanup_tempfile_(tempfile, tempfilename);
231 if(0 != rename(*tempfilename, filename)) {
232 cleanup_tempfile_(tempfile, tempfilename);
236 cleanup_tempfile_(tempfile, tempfilename);
241 bool get_file_stats_(const char *filename, struct stat *stats)
243 FLAC__ASSERT(0 != filename);
244 FLAC__ASSERT(0 != stats);
245 return (0 == stat(filename, stats));
248 void set_file_stats_(const char *filename, struct stat *stats)
250 struct utimbuf srctime;
252 FLAC__ASSERT(0 != filename);
253 FLAC__ASSERT(0 != stats);
255 srctime.actime = stats->st_atime;
256 srctime.modtime = stats->st_mtime;
257 (void)chmod(filename, stats->st_mode);
258 (void)utime(filename, &srctime);
259 #if !defined _MSC_VER && !defined __MINGW32__
260 (void)chown(filename, stats->st_uid, (gid_t)(-1));
261 (void)chown(filename, (uid_t)(-1), stats->st_gid);
265 #ifdef FLAC__VALGRIND_TESTING
266 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, ::FLAC__IOHandle handle)
268 FILE *stream = (FILE*)handle;
269 size_t ret = fwrite(ptr, size, nmemb, stream);
276 static int chain_seek_cb_(::FLAC__IOHandle handle, FLAC__int64 offset, int whence)
278 long o = (long)offset;
279 FLAC__ASSERT(offset == o);
280 return fseek((FILE*)handle, o, whence);
283 static FLAC__int64 chain_tell_cb_(::FLAC__IOHandle handle)
285 return ftell((FILE*)handle);
288 static int chain_eof_cb_(::FLAC__IOHandle handle)
290 return feof((FILE*)handle);
293 static bool write_chain_(FLAC::Metadata::Chain &chain, bool use_padding, bool preserve_file_stats, bool filename_based, const char *filename)
296 return chain.write(use_padding, preserve_file_stats);
298 ::FLAC__IOCallbacks callbacks;
300 memset(&callbacks, 0, sizeof(callbacks));
301 callbacks.read = (::FLAC__IOCallback_Read)fread;
302 #ifdef FLAC__VALGRIND_TESTING
303 callbacks.write = chain_write_cb_;
305 callbacks.write = (::FLAC__IOCallback_Write)fwrite;
307 callbacks.seek = chain_seek_cb_;
308 callbacks.eof = chain_eof_cb_;
310 if(chain.check_if_tempfile_needed(use_padding)) {
312 FILE *file, *tempfile;
314 if(preserve_file_stats) {
315 if(!get_file_stats_(filename, &stats))
318 if(0 == (file = fopen(filename, "rb")))
319 return false; /*@@@ chain status still says OK though */
320 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
322 cleanup_tempfile_(&tempfile, &tempfilename);
323 return false; /*@@@ chain status still says OK though */
325 if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks, (::FLAC__IOHandle)tempfile, callbacks)) {
333 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
335 if(preserve_file_stats)
336 set_file_stats_(filename, &stats);
339 FILE *file = fopen(filename, "r+b");
341 return false; /*@@@ chain status still says OK though */
342 if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks))
351 static bool read_chain_(FLAC::Metadata::Chain &chain, const char *filename, bool filename_based)
354 return chain.read(filename);
356 ::FLAC__IOCallbacks callbacks;
358 memset(&callbacks, 0, sizeof(callbacks));
359 callbacks.read = (::FLAC__IOCallback_Read)fread;
360 callbacks.seek = chain_seek_cb_;
361 callbacks.tell = chain_tell_cb_;
365 FILE *file = fopen(filename, "rb");
367 return false; /*@@@ chain status still says OK though */
368 ret = chain.read((::FLAC__IOHandle)file, callbacks);
375 /* function for comparing our metadata to a FLAC::Metadata::Chain */
377 static bool compare_chain_(FLAC::Metadata::Chain &chain, unsigned current_position, FLAC::Metadata::Prototype *current_block)
380 FLAC::Metadata::Iterator iterator;
383 printf("\tcomparing chain... ");
386 if(!iterator.is_valid())
387 return die_("allocating memory for iterator");
389 iterator.init(chain);
393 FLAC::Metadata::Prototype *block;
398 if(0 == (block = iterator.get_block()))
399 return die_("getting block from iterator");
401 if(*block != *our_metadata_.blocks[i])
402 return die_("metadata block mismatch");
406 next_ok = iterator.next();
407 } while(i < our_metadata_.num_blocks && next_ok);
410 return die_("chain has more blocks than expected");
412 if(i < our_metadata_.num_blocks)
413 return die_("short block count in chain");
415 if(0 != current_block) {
416 printf("CURRENT_POSITION... ");
419 if(*current_block != *our_metadata_.blocks[current_position])
420 return die_("metadata block mismatch");
428 ::FLAC__StreamDecoderWriteStatus OurFileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
433 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
434 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
436 printf("content... ");
440 return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
443 void OurFileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
445 /* don't bother checking if we've already hit an error */
449 printf("%d... ", mc_our_block_number_);
452 if(!ignore_metadata_) {
453 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
454 (void)die_("got more metadata blocks than expected");
455 error_occurred_ = true;
458 if(*our_metadata_.blocks[mc_our_block_number_] != metadata) {
459 (void)die_("metadata block mismatch");
460 error_occurred_ = true;
465 mc_our_block_number_++;
468 void OurFileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
470 error_occurred_ = true;
471 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
474 static bool generate_file_()
476 ::FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
477 ::FLAC__StreamMetadata *metadata[1];
479 printf("generating FLAC file for test\n");
481 while(our_metadata_.num_blocks > 0)
482 delete_from_our_metadata_(0);
484 streaminfo.is_last = false;
485 streaminfo.type = ::FLAC__METADATA_TYPE_STREAMINFO;
486 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
487 streaminfo.data.stream_info.min_blocksize = 576;
488 streaminfo.data.stream_info.max_blocksize = 576;
489 streaminfo.data.stream_info.min_framesize = 0;
490 streaminfo.data.stream_info.max_framesize = 0;
491 streaminfo.data.stream_info.sample_rate = 44100;
492 streaminfo.data.stream_info.channels = 1;
493 streaminfo.data.stream_info.bits_per_sample = 8;
494 streaminfo.data.stream_info.total_samples = 0;
495 memset(streaminfo.data.stream_info.md5sum, 0, 16);
498 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
499 vorbiscomment.is_last = false;
500 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
501 vorbiscomment.length = (4 + vendor_string_length) + 4;
502 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
503 vorbiscomment.data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length);
504 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length);
505 vorbiscomment.data.vorbis_comment.num_comments = 0;
506 vorbiscomment.data.vorbis_comment.comments = 0;
509 padding.is_last = true;
510 padding.type = ::FLAC__METADATA_TYPE_PADDING;
511 padding.length = 1234;
513 metadata[0] = &padding;
515 FLAC::Metadata::StreamInfo s(&streaminfo);
516 FLAC::Metadata::VorbisComment v(&vorbiscomment);
517 FLAC::Metadata::Padding p(&padding);
519 !insert_to_our_metadata_(&s, 0, /*copy=*/true) ||
520 !insert_to_our_metadata_(&v, 1, /*copy=*/true) ||
521 !insert_to_our_metadata_(&p, 2, /*copy=*/true)
523 return die_("priming our metadata");
525 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
526 return die_("creating the encoded file");
528 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
533 static bool test_file_(const char *filename, bool ignore_metadata)
535 OurFileDecoder decoder(ignore_metadata);
537 FLAC__ASSERT(0 != filename);
539 mc_our_block_number_ = 0;
540 decoder.error_occurred_ = false;
542 printf("\ttesting '%s'... ", filename);
545 if(!decoder.is_valid())
546 return die_("couldn't allocate decoder instance");
548 decoder.set_md5_checking(true);
549 decoder.set_filename(filename);
550 decoder.set_metadata_respond_all();
551 if(decoder.init() != ::FLAC__FILE_DECODER_OK) {
553 return die_("initializing decoder\n");
555 if(!decoder.process_until_end_of_file()) {
557 return die_("decoding file\n");
562 if(decoder.error_occurred_)
565 if(mc_our_block_number_ != our_metadata_.num_blocks)
566 return die_("short metadata block count");
572 static bool change_stats_(const char *filename, bool read_only)
574 if(!grabbag__file_change_stats(filename, read_only))
575 return die_("during grabbag__file_change_stats()");
580 static bool remove_file_(const char *filename)
582 while(our_metadata_.num_blocks > 0)
583 delete_from_our_metadata_(0);
585 if(!grabbag__file_remove_file(filename))
586 return die_("removing file");
591 static bool test_level_0_()
593 FLAC::Metadata::StreamInfo streaminfo;
594 FLAC::Metadata::VorbisComment *tags = 0;
596 printf("\n\n++++++ testing level 0 interface\n");
598 if(!generate_file_())
601 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
604 printf("testing FLAC::Metadata::get_streaminfo()... ");
606 if(!FLAC::Metadata::get_streaminfo(flacfile_, streaminfo))
607 return die_("during FLAC::Metadata::get_streaminfo()");
609 /* check to see if some basic data matches (c.f. generate_file_()) */
610 if(streaminfo.get_channels() != 1)
611 return die_("mismatch in streaminfo.get_channels()");
612 if(streaminfo.get_bits_per_sample() != 8)
613 return die_("mismatch in streaminfo.get_bits_per_sample()");
614 if(streaminfo.get_sample_rate() != 44100)
615 return die_("mismatch in streaminfo.get_sample_rate()");
616 if(streaminfo.get_min_blocksize() != 576)
617 return die_("mismatch in streaminfo.get_min_blocksize()");
618 if(streaminfo.get_max_blocksize() != 576)
619 return die_("mismatch in streaminfo.get_max_blocksize()");
623 printf("testing FLAC::Metadata::get_tags()... ");
625 if(!FLAC::Metadata::get_tags(flacfile_, tags))
626 return die_("during FLAC::Metadata::get_tags()");
628 /* check to see if some basic data matches (c.f. generate_file_()) */
629 if(tags->get_num_comments() != 0)
630 return die_("mismatch in tags->get_num_comments()");
636 if(!remove_file_(flacfile_))
642 static bool test_level_1_()
644 FLAC::Metadata::Prototype *block;
645 FLAC::Metadata::StreamInfo *streaminfo;
646 FLAC::Metadata::Padding *padding;
647 FLAC::Metadata::Application *app;
648 FLAC__byte data[1000];
649 unsigned our_current_position = 0;
651 // initialize 'data' to avoid Valgrind errors
652 memset(data, 0, sizeof(data));
654 printf("\n\n++++++ testing level 1 interface\n");
656 /************************************************************/
658 printf("simple iterator on read-only file\n");
660 if(!generate_file_())
663 if(!change_stats_(flacfile_, /*read_only=*/true))
666 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
669 FLAC::Metadata::SimpleIterator iterator;
671 if(!iterator.is_valid())
672 return die_("iterator.is_valid() returned false");
674 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
675 return die_("iterator.init() returned false");
677 printf("is writable = %u\n", (unsigned)iterator.is_writable());
678 if(iterator.is_writable())
679 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
681 printf("iterate forwards\n");
683 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
684 return die_("expected STREAMINFO type from iterator.get_block_type()");
685 if(0 == (block = iterator.get_block()))
686 return die_("getting block 0");
687 if(block->get_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
688 return die_("expected STREAMINFO type");
689 if(block->get_is_last())
690 return die_("expected is_last to be false");
691 if(block->get_length() != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
692 return die_("bad STREAMINFO length");
693 /* check to see if some basic data matches (c.f. generate_file_()) */
694 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
695 FLAC__ASSERT(0 != streaminfo);
696 if(streaminfo->get_channels() != 1)
697 return die_("mismatch in channels");
698 if(streaminfo->get_bits_per_sample() != 8)
699 return die_("mismatch in bits_per_sample");
700 if(streaminfo->get_sample_rate() != 44100)
701 return die_("mismatch in sample_rate");
702 if(streaminfo->get_min_blocksize() != 576)
703 return die_("mismatch in min_blocksize");
704 if(streaminfo->get_max_blocksize() != 576)
705 return die_("mismatch in max_blocksize");
706 // we will delete streaminfo a little later when we're really done with it...
709 return die_("forward iterator ended early");
710 our_current_position++;
713 return die_("forward iterator ended early");
714 our_current_position++;
716 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_PADDING)
717 return die_("expected PADDING type from iterator.get_block_type()");
718 if(0 == (block = iterator.get_block()))
719 return die_("getting block 1");
720 if(block->get_type() != ::FLAC__METADATA_TYPE_PADDING)
721 return die_("expected PADDING type");
722 if(!block->get_is_last())
723 return die_("expected is_last to be true");
724 /* check to see if some basic data matches (c.f. generate_file_()) */
725 if(block->get_length() != 1234)
726 return die_("bad PADDING length");
730 return die_("forward iterator returned true but should have returned false");
732 printf("iterate backwards\n");
734 return die_("reverse iterator ended early");
736 return die_("reverse iterator ended early");
738 return die_("reverse iterator returned true but should have returned false");
740 printf("testing iterator.set_block() on read-only file...\n");
742 if(!iterator.set_block(streaminfo, false))
743 printf("PASSED. iterator.set_block() returned false like it should\n");
745 return die_("iterator.set_block() returned true but shouldn't have");
749 /************************************************************/
751 printf("simple iterator on writable file\n");
753 if(!change_stats_(flacfile_, /*read-only=*/false))
756 printf("creating APPLICATION block\n");
758 if(0 == (app = new FLAC::Metadata::Application()))
759 return die_("new FLAC::Metadata::Application()");
760 app->set_id((const unsigned char *)"duh");
762 printf("creating PADDING block\n");
764 if(0 == (padding = new FLAC::Metadata::Padding()))
765 return die_("new FLAC::Metadata::Padding()");
766 padding->set_length(20);
768 FLAC::Metadata::SimpleIterator iterator;
770 if(!iterator.is_valid())
771 return die_("iterator.is_valid() returned false");
773 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
774 return die_("iterator.init() returned false");
775 our_current_position = 0;
777 printf("is writable = %u\n", (unsigned)iterator.is_writable());
779 printf("[S]VP\ttry to write over STREAMINFO block...\n");
780 if(!iterator.set_block(app, false))
781 printf("\titerator.set_block() returned false like it should\n");
783 return die_("iterator.set_block() returned true but shouldn't have");
785 printf("[S]VP\tnext\n");
787 return die_("iterator ended early\n");
788 our_current_position++;
790 printf("S[V]P\tnext\n");
792 return die_("iterator ended early\n");
793 our_current_position++;
795 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
796 padding->set_length(25);
797 if(!iterator.insert_block_after(padding, false))
798 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
799 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
802 printf("SVP[P]\tprev\n");
804 return die_("iterator ended early\n");
805 our_current_position--;
807 printf("SV[P]P\tprev\n");
809 return die_("iterator ended early\n");
810 our_current_position--;
812 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
813 padding->set_length(30);
814 if(!iterator.insert_block_after(padding, false))
815 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
816 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
819 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
822 printf("SV[P]PP\tprev\n");
824 return die_("iterator ended early\n");
825 our_current_position--;
827 printf("S[V]PPP\tprev\n");
829 return die_("iterator ended early\n");
830 our_current_position--;
832 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
833 if(iterator.delete_block(false))
834 return die_ss_("iterator.delete_block(false) should have returned false", iterator);
836 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
839 printf("[S]VPPP\tnext\n");
841 return die_("iterator ended early\n");
842 our_current_position++;
844 printf("S[V]PPP\tnext\n");
846 return die_("iterator ended early\n");
847 our_current_position++;
849 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
850 if(!iterator.delete_block(true))
851 return die_ss_("iterator.delete_block(true)", iterator);
852 our_current_position--;
854 printf("S[V]PPP\tnext\n");
856 return die_("iterator ended early\n");
857 our_current_position++;
859 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
860 if(!iterator.delete_block(false))
861 return die_ss_("iterator.delete_block(false)", iterator);
862 delete_from_our_metadata_(our_current_position--);
864 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
867 printf("S[V]PP\tnext\n");
869 return die_("iterator ended early\n");
870 our_current_position++;
872 printf("SV[P]P\tnext\n");
874 return die_("iterator ended early\n");
875 our_current_position++;
877 printf("SVP[P]\tdelete (last block), replace with padding\n");
878 if(!iterator.delete_block(true))
879 return die_ss_("iterator.delete_block(false)", iterator);
880 our_current_position--;
882 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
885 printf("SV[P]P\tnext\n");
887 return die_("iterator ended early\n");
888 our_current_position++;
890 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
891 if(!iterator.delete_block(false))
892 return die_ss_("iterator.delete_block(false)", iterator);
893 delete_from_our_metadata_(our_current_position--);
895 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
898 printf("SV[P]\tprev\n");
900 return die_("iterator ended early\n");
901 our_current_position--;
903 printf("S[V]P\tprev\n");
905 return die_("iterator ended early\n");
906 our_current_position--;
908 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
909 FLAC__ASSERT(our_current_position == 0);
910 block = iterator.get_block();
911 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
912 FLAC__ASSERT(0 != streaminfo);
913 streaminfo->set_sample_rate(32000);
914 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
915 return die_("copying object");
916 if(!iterator.set_block(block, false))
917 return die_ss_("iterator.set_block(block, false)", iterator);
920 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
923 printf("[S]VP\tnext\n");
925 return die_("iterator ended early\n");
926 our_current_position++;
928 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
929 app->set_id((const unsigned char *)"euh"); /* twiddle the id so that our comparison doesn't miss transposition */
930 if(!iterator.insert_block_after(app, true))
931 return die_ss_("iterator.insert_block_after(app, true)", iterator);
932 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
934 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
936 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
939 printf("SV[A]P\tnext\n");
941 return die_("iterator ended early\n");
942 our_current_position++;
944 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
945 app->set_id((const unsigned char *)"fuh"); /* twiddle the id */
946 if(!iterator.set_block(app, true))
947 return die_ss_("iterator.set_block(app, true)", iterator);
948 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
950 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
952 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
955 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
956 app->set_id((const unsigned char *)"guh"); /* twiddle the id */
957 if(!app->set_data(data, sizeof(data), true))
958 return die_("setting APPLICATION data");
959 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
960 return die_("copying object");
961 if(!iterator.set_block(app, false))
962 return die_ss_("iterator.set_block(app, false)", iterator);
964 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
967 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
968 app->set_id((const unsigned char *)"huh"); /* twiddle the id */
969 if(!app->set_data(data, 12, true))
970 return die_("setting APPLICATION data");
971 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
972 return die_("copying object");
973 if(!iterator.set_block(app, false))
974 return die_ss_("iterator.set_block(app, false)", iterator);
976 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
979 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
980 app->set_id((const unsigned char *)"iuh"); /* twiddle the id */
981 if(!app->set_data(data, sizeof(data), true))
982 return die_("setting APPLICATION data");
983 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
984 return die_("copying object");
985 add_to_padding_length_(our_current_position+1, -((int)sizeof(data) - 12));
986 if(!iterator.set_block(app, true))
987 return die_ss_("iterator.set_block(app, true)", iterator);
989 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
992 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
993 app->set_id((const unsigned char *)"juh"); /* twiddle the id */
994 if(!app->set_data(data, 23, true))
995 return die_("setting APPLICATION data");
996 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
997 return die_("copying object");
998 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
999 return die_("copying object");
1000 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH);
1001 if(!iterator.set_block(app, true))
1002 return die_ss_("iterator.set_block(app, true)", iterator);
1004 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1007 printf("SVA[A]PP\tnext\n");
1008 if(!iterator.next())
1009 return die_("iterator ended early\n");
1010 our_current_position++;
1012 printf("SVAA[P]P\tnext\n");
1013 if(!iterator.next())
1014 return die_("iterator ended early\n");
1015 our_current_position++;
1017 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1018 padding->set_length(5);
1019 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1020 return die_("copying object");
1021 if(!iterator.set_block(padding, false))
1022 return die_ss_("iterator.set_block(padding, false)", iterator);
1024 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1027 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1028 app->set_id((const unsigned char *)"kuh"); /* twiddle the id */
1029 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1030 return die_("copying object");
1031 if(!iterator.set_block(app, false))
1032 return die_ss_("iterator.set_block(app, false)", iterator);
1034 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1037 printf("SVAAP[A]\tset PADDING (equal)\n");
1038 padding->set_length(27);
1039 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1040 return die_("copying object");
1041 if(!iterator.set_block(padding, false))
1042 return die_ss_("iterator.set_block(padding, false)", iterator);
1044 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1047 printf("SVAAP[P]\tprev\n");
1048 if(!iterator.prev())
1049 return die_("iterator ended early\n");
1050 our_current_position--;
1052 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1053 if(!iterator.delete_block(false))
1054 return die_ss_("iterator.delete_block(false)", iterator);
1055 delete_from_our_metadata_(our_current_position--);
1057 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1060 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1061 if(!iterator.delete_block(false))
1062 return die_ss_("iterator.delete_block(false)", iterator);
1063 delete_from_our_metadata_(our_current_position--);
1065 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1068 printf("SV[A]P\tnext\n");
1069 if(!iterator.next())
1070 return die_("iterator ended early\n");
1071 our_current_position++;
1073 printf("SVA[P]\tinsert PADDING after\n");
1074 padding->set_length(5);
1075 if(!iterator.insert_block_after(padding, false))
1076 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1077 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1080 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1083 printf("SVAP[P]\tprev\n");
1084 if(!iterator.prev())
1085 return die_("iterator ended early\n");
1086 our_current_position--;
1088 printf("SVA[P]P\tprev\n");
1089 if(!iterator.prev())
1090 return die_("iterator ended early\n");
1091 our_current_position--;
1093 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1094 if(!app->set_data(data, 32, true))
1095 return die_("setting APPLICATION data");
1096 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1097 return die_("copying object");
1098 if(!iterator.set_block(app, true))
1099 return die_ss_("iterator.set_block(app, true)", iterator);
1101 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1104 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1105 if(!app->set_data(data, 60, true))
1106 return die_("setting APPLICATION data");
1107 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1108 return die_("copying object");
1109 if(!iterator.set_block(app, true))
1110 return die_ss_("iterator.set_block(app, true)", iterator);
1112 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1115 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1116 if(!app->set_data(data, 87, true))
1117 return die_("setting APPLICATION data");
1118 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1119 return die_("copying object");
1120 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1121 if(!iterator.set_block(app, true))
1122 return die_ss_("iterator.set_block(app, true)", iterator);
1124 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1127 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1128 if(!app->set_data(data, 91, true))
1129 return die_("setting APPLICATION data");
1130 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1131 return die_("copying object");
1132 delete_from_our_metadata_(our_current_position+1);
1133 if(!iterator.set_block(app, true))
1134 return die_ss_("iterator.set_block(app, true)", iterator);
1136 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1139 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1140 if(!app->set_data(data, 100, true))
1141 return die_("setting APPLICATION data");
1142 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1143 return die_("copying object");
1144 delete_from_our_metadata_(our_current_position+1);
1145 our_metadata_.blocks[our_current_position]->set_is_last(true);
1146 if(!iterator.set_block(app, true))
1147 return die_ss_("iterator.set_block(app, true)", iterator);
1149 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1152 printf("SV[A]\tset PADDING (equal size)\n");
1153 padding->set_length(app->get_length());
1154 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1155 return die_("copying object");
1156 if(!iterator.set_block(padding, true))
1157 return die_ss_("iterator.set_block(padding, true)", iterator);
1159 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1162 printf("SV[P]\tinsert PADDING after\n");
1163 if(!iterator.insert_block_after(padding, false))
1164 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1165 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1168 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1171 printf("SVP[P]\tinsert PADDING after\n");
1172 padding->set_length(5);
1173 if(!iterator.insert_block_after(padding, false))
1174 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1175 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1178 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1181 printf("SVPP[P]\tprev\n");
1182 if(!iterator.prev())
1183 return die_("iterator ended early\n");
1184 our_current_position--;
1186 printf("SVP[P]P\tprev\n");
1187 if(!iterator.prev())
1188 return die_("iterator ended early\n");
1189 our_current_position--;
1191 printf("SV[P]PP\tprev\n");
1192 if(!iterator.prev())
1193 return die_("iterator ended early\n");
1194 our_current_position--;
1196 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1197 if(!app->set_data(data, 101, true))
1198 return die_("setting APPLICATION data");
1199 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1200 return die_("copying object");
1201 if(!iterator.insert_block_after(app, true))
1202 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1204 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1207 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1208 if(!iterator.delete_block(false))
1209 return die_ss_("iterator.delete_block(false)", iterator);
1210 delete_from_our_metadata_(our_current_position--);
1212 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1215 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1216 if(!app->set_data(data, 97, true))
1217 return die_("setting APPLICATION data");
1218 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1219 return die_("copying object");
1220 if(!iterator.insert_block_after(app, true))
1221 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1223 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1226 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1227 if(!iterator.delete_block(false))
1228 return die_ss_("iterator.delete_block(false)", iterator);
1229 delete_from_our_metadata_(our_current_position--);
1231 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1234 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1235 if(!app->set_data(data, 100, true))
1236 return die_("setting APPLICATION data");
1237 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1238 return die_("copying object");
1239 delete_from_our_metadata_(our_current_position+1);
1240 if(!iterator.insert_block_after(app, true))
1241 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1243 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1246 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1247 if(!iterator.delete_block(false))
1248 return die_ss_("iterator.delete_block(false)", iterator);
1249 delete_from_our_metadata_(our_current_position--);
1251 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1254 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1255 if(!app->set_data(data, 96, true))
1256 return die_("setting APPLICATION data");
1257 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1258 return die_("copying object");
1259 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1260 if(!iterator.insert_block_after(app, true))
1261 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1263 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1266 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1267 if(!iterator.delete_block(false))
1268 return die_ss_("iterator.delete_block(false)", iterator);
1269 delete_from_our_metadata_(our_current_position--);
1271 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1274 printf("S[V]PP\tnext\n");
1275 if(!iterator.next())
1276 return die_("iterator ended early\n");
1277 our_current_position++;
1279 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1280 if(!iterator.delete_block(false))
1281 return die_ss_("iterator.delete_block(false)", iterator);
1282 delete_from_our_metadata_(our_current_position--);
1284 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1287 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1288 if(!app->set_data(data, 1, true))
1289 return die_("setting APPLICATION data");
1290 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1291 return die_("copying object");
1292 delete_from_our_metadata_(our_current_position+1);
1293 if(!iterator.insert_block_after(app, true))
1294 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1296 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1303 if(!remove_file_(flacfile_))
1309 static bool test_level_2_(bool filename_based)
1311 FLAC::Metadata::Prototype *block;
1312 FLAC::Metadata::StreamInfo *streaminfo;
1313 FLAC::Metadata::Application *app;
1314 FLAC::Metadata::Padding *padding;
1315 FLAC__byte data[2000];
1316 unsigned our_current_position;
1318 // initialize 'data' to avoid Valgrind errors
1319 memset(data, 0, sizeof(data));
1321 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1323 printf("generate read-only file\n");
1325 if(!generate_file_())
1328 if(!change_stats_(flacfile_, /*read_only=*/true))
1331 printf("create chain\n");
1332 FLAC::Metadata::Chain chain;
1333 if(!chain.is_valid())
1334 return die_("allocating memory for chain");
1336 printf("read chain\n");
1338 if(!read_chain_(chain, flacfile_, filename_based))
1339 return die_c_("reading chain", chain.status());
1341 printf("[S]VP\ttest initial metadata\n");
1343 if(!compare_chain_(chain, 0, 0))
1345 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1348 printf("switch file to read-write\n");
1350 if(!change_stats_(flacfile_, /*read-only=*/false))
1353 printf("create iterator\n");
1355 FLAC::Metadata::Iterator iterator;
1356 if(!iterator.is_valid())
1357 return die_("allocating memory for iterator");
1359 our_current_position = 0;
1361 iterator.init(chain);
1363 if(0 == (block = iterator.get_block()))
1364 return die_("getting block from iterator");
1366 FLAC__ASSERT(block->get_type() == FLAC__METADATA_TYPE_STREAMINFO);
1368 printf("[S]VP\tmodify STREAMINFO, write\n");
1370 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
1371 FLAC__ASSERT(0 != streaminfo);
1372 streaminfo->set_sample_rate(32000);
1373 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1374 return die_("copying object");
1377 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1378 return die_c_("during chain.write(false, true)", chain.status());
1379 block = iterator.get_block();
1380 if(!compare_chain_(chain, our_current_position, block))
1383 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1386 printf("[S]VP\tnext\n");
1387 if(!iterator.next())
1388 return die_("iterator ended early\n");
1389 our_current_position++;
1391 printf("S[V]P\tnext\n");
1392 if(!iterator.next())
1393 return die_("iterator ended early\n");
1394 our_current_position++;
1396 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1397 if(0 == (block = iterator.get_block()))
1398 return die_("getting block from iterator");
1399 if(0 == (app = new FLAC::Metadata::Application()))
1400 return die_("new FLAC::Metadata::Application()");
1401 app->set_id((const unsigned char *)"duh");
1402 if(!app->set_data(data, block->get_length()-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1403 return die_("setting APPLICATION data");
1405 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1406 return die_("copying object");
1407 if(!iterator.set_block(app))
1408 return die_c_("iterator.set_block(app)", chain.status());
1410 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1411 return die_c_("during chain.write(false, false)", chain.status());
1412 block = iterator.get_block();
1413 if(!compare_chain_(chain, our_current_position, block))
1416 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1419 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1420 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1421 return die_("copying object");
1422 if(!app->set_data(data, 26, true))
1423 return die_("setting APPLICATION data");
1424 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1425 return die_("copying object");
1426 if(!iterator.set_block(app))
1427 return die_c_("iterator.set_block(app)", chain.status());
1429 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1430 return die_c_("during chain.write(false, false)", chain.status());
1431 block = iterator.get_block();
1432 if(!compare_chain_(chain, our_current_position, block))
1435 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1438 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1439 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1440 return die_("copying object");
1441 if(!app->set_data(data, 28, true))
1442 return die_("setting APPLICATION data");
1443 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1444 return die_("copying object");
1445 if(!iterator.set_block(app))
1446 return die_c_("iterator.set_block(app)", chain.status());
1448 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1449 return die_c_("during chain.write(false, false)", chain.status());
1450 block = iterator.get_block();
1451 if(!compare_chain_(chain, our_current_position, block))
1454 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1457 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1458 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1459 return die_("copying object");
1460 if(!app->set_data(data, 36, true))
1461 return die_("setting APPLICATION data");
1462 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1463 return die_("copying object");
1464 if(!iterator.set_block(app))
1465 return die_c_("iterator.set_block(app)", chain.status());
1467 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1468 return die_c_("during chain.write(false, false)", chain.status());
1469 block = iterator.get_block();
1470 if(!compare_chain_(chain, our_current_position, block))
1473 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1476 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1477 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1478 return die_("copying object");
1479 if(!app->set_data(data, 33, true))
1480 return die_("setting APPLICATION data");
1481 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1482 return die_("copying object");
1483 if(!iterator.set_block(app))
1484 return die_c_("iterator.set_block(app)", chain.status());
1486 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1487 return die_c_("during chain.write(true, false)", chain.status());
1488 block = iterator.get_block();
1489 if(!compare_chain_(chain, our_current_position, block))
1492 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1495 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1496 if(0 == (padding = new FLAC::Metadata::Padding()))
1497 return die_("creating PADDING block");
1498 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1499 return die_("copying object");
1500 if(!app->set_data(data, 29, true))
1501 return die_("setting APPLICATION data");
1502 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1503 return die_("copying object");
1504 padding->set_length(0);
1505 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1506 return die_("internal error");
1507 if(!iterator.set_block(app))
1508 return die_c_("iterator.set_block(app)", chain.status());
1510 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1511 return die_c_("during chain.write(true, false)", chain.status());
1512 block = iterator.get_block();
1513 if(!compare_chain_(chain, our_current_position, block))
1516 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1519 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1520 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1521 return die_("copying object");
1522 if(!app->set_data(data, 16, true))
1523 return die_("setting APPLICATION data");
1524 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1525 return die_("copying object");
1526 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(13);
1527 if(!iterator.set_block(app))
1528 return die_c_("iterator.set_block(app)", chain.status());
1530 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1531 return die_c_("during chain.write(true, false)", chain.status());
1532 block = iterator.get_block();
1533 if(!compare_chain_(chain, our_current_position, block))
1536 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1539 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1540 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1541 return die_("copying object");
1542 if(!app->set_data(data, 50, true))
1543 return die_("setting APPLICATION data");
1544 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1545 return die_("copying object");
1546 if(!iterator.set_block(app))
1547 return die_c_("iterator.set_block(app)", chain.status());
1549 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1550 return die_c_("during chain.write(true, false)", chain.status());
1551 block = iterator.get_block();
1552 if(!compare_chain_(chain, our_current_position, block))
1555 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1558 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1559 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1560 return die_("copying object");
1561 if(!app->set_data(data, 56, true))
1562 return die_("setting APPLICATION data");
1563 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1564 return die_("copying object");
1565 add_to_padding_length_(our_current_position+1, -(56 - 50));
1566 if(!iterator.set_block(app))
1567 return die_c_("iterator.set_block(app)", chain.status());
1569 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1570 return die_c_("during chain.write(true, false)", chain.status());
1571 block = iterator.get_block();
1572 if(!compare_chain_(chain, our_current_position, block))
1575 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1578 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1579 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1580 return die_("copying object");
1581 if(!app->set_data(data, 67, true))
1582 return die_("setting APPLICATION data");
1583 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1584 return die_("copying object");
1585 delete_from_our_metadata_(our_current_position+1);
1586 if(!iterator.set_block(app))
1587 return die_c_("iterator.set_block(app)", chain.status());
1589 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1590 return die_c_("during chain.write(true, false)", chain.status());
1591 block = iterator.get_block();
1592 if(!compare_chain_(chain, our_current_position, block))
1595 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1598 printf("SV[A]\tprev\n");
1599 if(!iterator.prev())
1600 return die_("iterator ended early\n");
1601 our_current_position--;
1603 printf("S[V]A\tprev\n");
1604 if(!iterator.prev())
1605 return die_("iterator ended early\n");
1606 our_current_position--;
1608 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1609 if(0 == (padding = new FLAC::Metadata::Padding()))
1610 return die_("creating PADDING block");
1611 padding->set_length(30);
1612 if(!iterator.insert_block_before(padding))
1613 printf("\titerator.insert_block_before() returned false like it should\n");
1615 return die_("iterator.insert_block_before() should have returned false");
1617 printf("[S]VA\tnext\n");
1618 if(!iterator.next())
1619 return die_("iterator ended early\n");
1620 our_current_position++;
1622 printf("S[V]A\tinsert PADDING after\n");
1623 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1624 return die_("copying metadata");
1625 if(!iterator.insert_block_after(padding))
1626 return die_("iterator.insert_block_after(padding)");
1628 block = iterator.get_block();
1629 if(!compare_chain_(chain, our_current_position, block))
1633 printf("SV[P]A\tinsert PADDING before\n");
1634 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1635 return die_("creating PADDING block");
1636 padding->set_length(17);
1637 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1638 return die_("copying metadata");
1639 if(!iterator.insert_block_before(padding))
1640 return die_("iterator.insert_block_before(padding)");
1642 block = iterator.get_block();
1643 if(!compare_chain_(chain, our_current_position, block))
1647 printf("SV[P]PA\tinsert PADDING before\n");
1648 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1649 return die_("creating PADDING block");
1650 padding->set_length(0);
1651 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1652 return die_("copying metadata");
1653 if(!iterator.insert_block_before(padding))
1654 return die_("iterator.insert_block_before(padding)");
1656 block = iterator.get_block();
1657 if(!compare_chain_(chain, our_current_position, block))
1661 printf("SV[P]PPA\tnext\n");
1662 if(!iterator.next())
1663 return die_("iterator ended early\n");
1664 our_current_position++;
1666 printf("SVP[P]PA\tnext\n");
1667 if(!iterator.next())
1668 return die_("iterator ended early\n");
1669 our_current_position++;
1671 printf("SVPP[P]A\tnext\n");
1672 if(!iterator.next())
1673 return die_("iterator ended early\n");
1674 our_current_position++;
1676 printf("SVPPP[A]\tinsert PADDING after\n");
1677 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1678 return die_("creating PADDING block");
1679 padding->set_length(57);
1680 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1681 return die_("copying metadata");
1682 if(!iterator.insert_block_after(padding))
1683 return die_("iterator.insert_block_after(padding)");
1685 block = iterator.get_block();
1686 if(!compare_chain_(chain, our_current_position, block))
1690 printf("SVPPPA[P]\tinsert PADDING before\n");
1691 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1692 return die_("creating PADDING block");
1693 padding->set_length(99);
1694 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1695 return die_("copying metadata");
1696 if(!iterator.insert_block_before(padding))
1697 return die_("iterator.insert_block_before(padding)");
1699 block = iterator.get_block();
1700 if(!compare_chain_(chain, our_current_position, block))
1705 our_current_position = 0;
1707 printf("SVPPPAPP\tmerge padding\n");
1708 chain.merge_padding();
1709 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->get_length());
1710 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->get_length());
1711 add_to_padding_length_(6, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->get_length());
1712 delete_from_our_metadata_(7);
1713 delete_from_our_metadata_(4);
1714 delete_from_our_metadata_(3);
1716 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1717 return die_c_("during chain.write(true, false)", chain.status());
1718 if(!compare_chain_(chain, 0, 0))
1720 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1723 printf("SVPAP\tsort padding\n");
1724 chain.sort_padding();
1725 add_to_padding_length_(4, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->get_length());
1726 delete_from_our_metadata_(2);
1728 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1729 return die_c_("during chain.write(true, false)", chain.status());
1730 if(!compare_chain_(chain, 0, 0))
1732 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1735 printf("create iterator\n");
1737 FLAC::Metadata::Iterator iterator;
1738 if(!iterator.is_valid())
1739 return die_("allocating memory for iterator");
1741 our_current_position = 0;
1743 iterator.init(chain);
1745 printf("[S]VAP\tnext\n");
1746 if(!iterator.next())
1747 return die_("iterator ended early\n");
1748 our_current_position++;
1750 printf("S[V]AP\tnext\n");
1751 if(!iterator.next())
1752 return die_("iterator ended early\n");
1753 our_current_position++;
1755 printf("SV[A]P\tdelete middle block, replace with padding\n");
1756 if(0 == (padding = new FLAC::Metadata::Padding()))
1757 return die_("creating PADDING block");
1758 padding->set_length(71);
1759 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1760 return die_("copying object");
1761 if(!iterator.delete_block(/*replace_with_padding=*/true))
1762 return die_c_("iterator.delete_block(true)", chain.status());
1764 block = iterator.get_block();
1765 if(!compare_chain_(chain, our_current_position, block))
1769 printf("S[V]PP\tnext\n");
1770 if(!iterator.next())
1771 return die_("iterator ended early\n");
1772 our_current_position++;
1774 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1775 delete_from_our_metadata_(our_current_position--);
1776 if(!iterator.delete_block(/*replace_with_padding=*/false))
1777 return die_c_("iterator.delete_block(false)", chain.status());
1779 block = iterator.get_block();
1780 if(!compare_chain_(chain, our_current_position, block))
1784 printf("S[V]P\tnext\n");
1785 if(!iterator.next())
1786 return die_("iterator ended early\n");
1787 our_current_position++;
1789 printf("SV[P]\tdelete last block, replace with padding\n");
1790 if(0 == (padding = new FLAC::Metadata::Padding()))
1791 return die_("creating PADDING block");
1792 padding->set_length(219);
1793 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1794 return die_("copying object");
1795 if(!iterator.delete_block(/*replace_with_padding=*/true))
1796 return die_c_("iterator.delete_block(true)", chain.status());
1798 block = iterator.get_block();
1799 if(!compare_chain_(chain, our_current_position, block))
1803 printf("S[V]P\tnext\n");
1804 if(!iterator.next())
1805 return die_("iterator ended early\n");
1806 our_current_position++;
1808 printf("SV[P]\tdelete last block, don't replace with padding\n");
1809 delete_from_our_metadata_(our_current_position--);
1810 if(!iterator.delete_block(/*replace_with_padding=*/false))
1811 return die_c_("iterator.delete_block(false)", chain.status());
1813 block = iterator.get_block();
1814 if(!compare_chain_(chain, our_current_position, block))
1818 printf("S[V]\tprev\n");
1819 if(!iterator.prev())
1820 return die_("iterator ended early\n");
1821 our_current_position--;
1823 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1824 if(iterator.delete_block(/*replace_with_padding=*/false))
1825 return die_("iterator.delete_block() on STREAMINFO should have failed but didn't");
1827 block = iterator.get_block();
1828 if(!compare_chain_(chain, our_current_position, block))
1832 } // delete iterator
1833 our_current_position = 0;
1835 printf("SV\tmerge padding\n");
1836 chain.merge_padding();
1838 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1839 return die_c_("during chain.write(false, false)", chain.status());
1840 if(!compare_chain_(chain, 0, 0))
1842 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1845 printf("SV\tsort padding\n");
1846 chain.sort_padding();
1848 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1849 return die_c_("during chain.write(false, false)", chain.status());
1850 if(!compare_chain_(chain, 0, 0))
1852 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1855 if(!remove_file_(flacfile_))
1861 static bool test_level_2_misc_()
1863 ::FLAC__IOCallbacks callbacks;
1865 memset(&callbacks, 0, sizeof(callbacks));
1866 callbacks.read = (::FLAC__IOCallback_Read)fread;
1867 #ifdef FLAC__VALGRIND_TESTING
1868 callbacks.write = chain_write_cb_;
1870 callbacks.write = (::FLAC__IOCallback_Write)fwrite;
1872 callbacks.seek = chain_seek_cb_;
1873 callbacks.tell = chain_tell_cb_;
1874 callbacks.eof = chain_eof_cb_;
1876 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1878 printf("generate file\n");
1880 if(!generate_file_())
1883 printf("create chain\n");
1884 FLAC::Metadata::Chain chain;
1885 if(!chain.is_valid())
1886 return die_("allocating chain");
1888 printf("read chain (filename-based)\n");
1890 if(!chain.read(flacfile_))
1891 return die_c_("reading chain", chain.status());
1893 printf("write chain with wrong method Chain::write(with callbacks)\n");
1895 if(chain.write(/*use_padding=*/false, 0, callbacks))
1896 return die_c_("mismatched write should have failed", chain.status());
1897 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1898 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1899 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1902 printf("read chain (filename-based)\n");
1904 if(!chain.read(flacfile_))
1905 return die_c_("reading chain", chain.status());
1907 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
1909 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
1910 return die_c_("mismatched write should have failed", chain.status());
1911 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1912 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1913 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1916 printf("read chain (callback-based)\n");
1918 FILE *file = fopen(flacfile_, "rb");
1920 return die_("opening file");
1921 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1923 return die_c_("reading chain", chain.status());
1928 printf("write chain with wrong method write()\n");
1930 if(chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false))
1931 return die_c_("mismatched write should have failed", chain.status());
1932 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1933 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1934 printf(" OK: write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1937 printf("read chain (callback-based)\n");
1939 FILE *file = fopen(flacfile_, "rb");
1941 return die_("opening file");
1942 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1944 return die_c_("reading chain", chain.status());
1949 printf("testing Chain::check_if_tempfile_needed()... ");
1951 if(!chain.check_if_tempfile_needed(/*use_padding=*/false))
1952 printf("OK: Chain::check_if_tempfile_needed() returned false like it should\n");
1954 return die_("Chain::check_if_tempfile_needed() returned true but shouldn't have");
1956 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
1958 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
1959 return die_c_("mismatched write should have failed", chain.status());
1960 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1961 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
1962 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1965 printf("read chain (callback-based)\n");
1967 FILE *file = fopen(flacfile_, "rb");
1969 return die_("opening file");
1970 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1972 return die_c_("reading chain", chain.status());
1977 printf("create iterator\n");
1979 FLAC::Metadata::Iterator iterator;
1980 if(!iterator.is_valid())
1981 return die_("allocating memory for iterator");
1983 iterator.init(chain);
1985 printf("[S]VP\tnext\n");
1986 if(!iterator.next())
1987 return die_("iterator ended early\n");
1989 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1990 if(!iterator.delete_block(/*replace_with_padding=*/false))
1991 return die_c_("block delete failed\n", chain.status());
1993 printf("testing Chain::check_if_tempfile_needed()... ");
1995 if(chain.check_if_tempfile_needed(/*use_padding=*/false))
1996 printf("OK: Chain::check_if_tempfile_needed() returned true like it should\n");
1998 return die_("Chain::check_if_tempfile_needed() returned false but shouldn't have");
2000 printf("write chain with wrong method Chain::write(with callbacks)\n");
2002 if(chain.write(/*use_padding=*/false, 0, callbacks))
2003 return die_c_("mismatched write should have failed", chain.status());
2004 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2005 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
2006 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2009 } // delete iterator
2011 if(!remove_file_(flacfile_))
2017 bool test_metadata_file_manipulation()
2019 printf("\n+++ libFLAC++ unit test: metadata manipulation\n\n");
2021 our_metadata_.num_blocks = 0;
2023 if(!test_level_0_())
2026 if(!test_level_1_())
2029 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2031 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2033 if(!test_level_2_misc_())