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+1);
504 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
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;
595 printf("\n\n++++++ testing level 0 interface\n");
597 if(!generate_file_())
600 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
603 printf("testing FLAC::Metadata::get_streaminfo()... ");
605 if(!FLAC::Metadata::get_streaminfo(flacfile_, streaminfo))
606 return die_("during FLAC::Metadata::get_streaminfo()");
608 /* check to see if some basic data matches (c.f. generate_file_()) */
609 if(streaminfo.get_channels() != 1)
610 return die_("mismatch in streaminfo.get_channels()");
611 if(streaminfo.get_bits_per_sample() != 8)
612 return die_("mismatch in streaminfo.get_bits_per_sample()");
613 if(streaminfo.get_sample_rate() != 44100)
614 return die_("mismatch in streaminfo.get_sample_rate()");
615 if(streaminfo.get_min_blocksize() != 576)
616 return die_("mismatch in streaminfo.get_min_blocksize()");
617 if(streaminfo.get_max_blocksize() != 576)
618 return die_("mismatch in streaminfo.get_max_blocksize()");
623 printf("testing FLAC::Metadata::get_tags(VorbisComment *&)... ");
625 FLAC::Metadata::VorbisComment *tags = 0;
627 if(!FLAC::Metadata::get_tags(flacfile_, tags))
628 return die_("during FLAC::Metadata::get_tags()");
630 /* check to see if some basic data matches (c.f. generate_file_()) */
631 if(tags->get_num_comments() != 0)
632 return die_("mismatch in tags->get_num_comments()");
640 printf("testing FLAC::Metadata::get_tags(VorbisComment &)... ");
642 FLAC::Metadata::VorbisComment tags;
644 if(!FLAC::Metadata::get_tags(flacfile_, tags))
645 return die_("during FLAC::Metadata::get_tags()");
647 /* check to see if some basic data matches (c.f. generate_file_()) */
648 if(tags.get_num_comments() != 0)
649 return die_("mismatch in tags.get_num_comments()");
654 if(!remove_file_(flacfile_))
660 static bool test_level_1_()
662 FLAC::Metadata::Prototype *block;
663 FLAC::Metadata::StreamInfo *streaminfo;
664 FLAC::Metadata::Padding *padding;
665 FLAC::Metadata::Application *app;
666 FLAC__byte data[1000];
667 unsigned our_current_position = 0;
669 // initialize 'data' to avoid Valgrind errors
670 memset(data, 0, sizeof(data));
672 printf("\n\n++++++ testing level 1 interface\n");
674 /************************************************************/
676 printf("simple iterator on read-only file\n");
678 if(!generate_file_())
681 if(!change_stats_(flacfile_, /*read_only=*/true))
684 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
687 FLAC::Metadata::SimpleIterator iterator;
689 if(!iterator.is_valid())
690 return die_("iterator.is_valid() returned false");
692 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
693 return die_("iterator.init() returned false");
695 printf("is writable = %u\n", (unsigned)iterator.is_writable());
696 if(iterator.is_writable())
697 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
699 printf("iterate forwards\n");
701 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
702 return die_("expected STREAMINFO type from iterator.get_block_type()");
703 if(0 == (block = iterator.get_block()))
704 return die_("getting block 0");
705 if(block->get_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
706 return die_("expected STREAMINFO type");
707 if(block->get_is_last())
708 return die_("expected is_last to be false");
709 if(block->get_length() != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
710 return die_("bad STREAMINFO length");
711 /* check to see if some basic data matches (c.f. generate_file_()) */
712 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
713 FLAC__ASSERT(0 != streaminfo);
714 if(streaminfo->get_channels() != 1)
715 return die_("mismatch in channels");
716 if(streaminfo->get_bits_per_sample() != 8)
717 return die_("mismatch in bits_per_sample");
718 if(streaminfo->get_sample_rate() != 44100)
719 return die_("mismatch in sample_rate");
720 if(streaminfo->get_min_blocksize() != 576)
721 return die_("mismatch in min_blocksize");
722 if(streaminfo->get_max_blocksize() != 576)
723 return die_("mismatch in max_blocksize");
724 // we will delete streaminfo a little later when we're really done with it...
727 return die_("forward iterator ended early");
728 our_current_position++;
731 return die_("forward iterator ended early");
732 our_current_position++;
734 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_PADDING)
735 return die_("expected PADDING type from iterator.get_block_type()");
736 if(0 == (block = iterator.get_block()))
737 return die_("getting block 1");
738 if(block->get_type() != ::FLAC__METADATA_TYPE_PADDING)
739 return die_("expected PADDING type");
740 if(!block->get_is_last())
741 return die_("expected is_last to be true");
742 /* check to see if some basic data matches (c.f. generate_file_()) */
743 if(block->get_length() != 1234)
744 return die_("bad PADDING length");
748 return die_("forward iterator returned true but should have returned false");
750 printf("iterate backwards\n");
752 return die_("reverse iterator ended early");
754 return die_("reverse iterator ended early");
756 return die_("reverse iterator returned true but should have returned false");
758 printf("testing iterator.set_block() on read-only file...\n");
760 if(!iterator.set_block(streaminfo, false))
761 printf("PASSED. iterator.set_block() returned false like it should\n");
763 return die_("iterator.set_block() returned true but shouldn't have");
767 /************************************************************/
769 printf("simple iterator on writable file\n");
771 if(!change_stats_(flacfile_, /*read-only=*/false))
774 printf("creating APPLICATION block\n");
776 if(0 == (app = new FLAC::Metadata::Application()))
777 return die_("new FLAC::Metadata::Application()");
778 app->set_id((const unsigned char *)"duh");
780 printf("creating PADDING block\n");
782 if(0 == (padding = new FLAC::Metadata::Padding()))
783 return die_("new FLAC::Metadata::Padding()");
784 padding->set_length(20);
786 FLAC::Metadata::SimpleIterator iterator;
788 if(!iterator.is_valid())
789 return die_("iterator.is_valid() returned false");
791 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
792 return die_("iterator.init() returned false");
793 our_current_position = 0;
795 printf("is writable = %u\n", (unsigned)iterator.is_writable());
797 printf("[S]VP\ttry to write over STREAMINFO block...\n");
798 if(!iterator.set_block(app, false))
799 printf("\titerator.set_block() returned false like it should\n");
801 return die_("iterator.set_block() returned true but shouldn't have");
803 printf("[S]VP\tnext\n");
805 return die_("iterator ended early\n");
806 our_current_position++;
808 printf("S[V]P\tnext\n");
810 return die_("iterator ended early\n");
811 our_current_position++;
813 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
814 padding->set_length(25);
815 if(!iterator.insert_block_after(padding, false))
816 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
817 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
820 printf("SVP[P]\tprev\n");
822 return die_("iterator ended early\n");
823 our_current_position--;
825 printf("SV[P]P\tprev\n");
827 return die_("iterator ended early\n");
828 our_current_position--;
830 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
831 padding->set_length(30);
832 if(!iterator.insert_block_after(padding, false))
833 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
834 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
837 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
840 printf("SV[P]PP\tprev\n");
842 return die_("iterator ended early\n");
843 our_current_position--;
845 printf("S[V]PPP\tprev\n");
847 return die_("iterator ended early\n");
848 our_current_position--;
850 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
851 if(iterator.delete_block(false))
852 return die_ss_("iterator.delete_block(false) should have returned false", iterator);
854 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
857 printf("[S]VPPP\tnext\n");
859 return die_("iterator ended early\n");
860 our_current_position++;
862 printf("S[V]PPP\tnext\n");
864 return die_("iterator ended early\n");
865 our_current_position++;
867 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
868 if(!iterator.delete_block(true))
869 return die_ss_("iterator.delete_block(true)", iterator);
870 our_current_position--;
872 printf("S[V]PPP\tnext\n");
874 return die_("iterator ended early\n");
875 our_current_position++;
877 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
878 if(!iterator.delete_block(false))
879 return die_ss_("iterator.delete_block(false)", iterator);
880 delete_from_our_metadata_(our_current_position--);
882 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
885 printf("S[V]PP\tnext\n");
887 return die_("iterator ended early\n");
888 our_current_position++;
890 printf("SV[P]P\tnext\n");
892 return die_("iterator ended early\n");
893 our_current_position++;
895 printf("SVP[P]\tdelete (last block), replace with padding\n");
896 if(!iterator.delete_block(true))
897 return die_ss_("iterator.delete_block(false)", iterator);
898 our_current_position--;
900 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
903 printf("SV[P]P\tnext\n");
905 return die_("iterator ended early\n");
906 our_current_position++;
908 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
909 if(!iterator.delete_block(false))
910 return die_ss_("iterator.delete_block(false)", iterator);
911 delete_from_our_metadata_(our_current_position--);
913 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
916 printf("SV[P]\tprev\n");
918 return die_("iterator ended early\n");
919 our_current_position--;
921 printf("S[V]P\tprev\n");
923 return die_("iterator ended early\n");
924 our_current_position--;
926 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
927 FLAC__ASSERT(our_current_position == 0);
928 block = iterator.get_block();
929 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
930 FLAC__ASSERT(0 != streaminfo);
931 streaminfo->set_sample_rate(32000);
932 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
933 return die_("copying object");
934 if(!iterator.set_block(block, false))
935 return die_ss_("iterator.set_block(block, false)", iterator);
938 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
941 printf("[S]VP\tnext\n");
943 return die_("iterator ended early\n");
944 our_current_position++;
946 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
947 app->set_id((const unsigned char *)"euh"); /* twiddle the id so that our comparison doesn't miss transposition */
948 if(!iterator.insert_block_after(app, true))
949 return die_ss_("iterator.insert_block_after(app, true)", iterator);
950 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
952 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
954 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
957 printf("SV[A]P\tnext\n");
959 return die_("iterator ended early\n");
960 our_current_position++;
962 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
963 app->set_id((const unsigned char *)"fuh"); /* twiddle the id */
964 if(!iterator.set_block(app, true))
965 return die_ss_("iterator.set_block(app, true)", iterator);
966 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
968 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
970 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
973 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
974 app->set_id((const unsigned char *)"guh"); /* twiddle the id */
975 if(!app->set_data(data, sizeof(data), true))
976 return die_("setting APPLICATION data");
977 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
978 return die_("copying object");
979 if(!iterator.set_block(app, false))
980 return die_ss_("iterator.set_block(app, false)", iterator);
982 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
985 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
986 app->set_id((const unsigned char *)"huh"); /* twiddle the id */
987 if(!app->set_data(data, 12, true))
988 return die_("setting APPLICATION data");
989 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
990 return die_("copying object");
991 if(!iterator.set_block(app, false))
992 return die_ss_("iterator.set_block(app, false)", iterator);
994 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
997 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
998 app->set_id((const unsigned char *)"iuh"); /* twiddle the id */
999 if(!app->set_data(data, sizeof(data), true))
1000 return die_("setting APPLICATION data");
1001 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1002 return die_("copying object");
1003 add_to_padding_length_(our_current_position+1, -((int)sizeof(data) - 12));
1004 if(!iterator.set_block(app, true))
1005 return die_ss_("iterator.set_block(app, true)", iterator);
1007 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1010 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1011 app->set_id((const unsigned char *)"juh"); /* twiddle the id */
1012 if(!app->set_data(data, 23, true))
1013 return die_("setting APPLICATION data");
1014 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1015 return die_("copying object");
1016 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1017 return die_("copying object");
1018 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH);
1019 if(!iterator.set_block(app, true))
1020 return die_ss_("iterator.set_block(app, true)", iterator);
1022 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1025 printf("SVA[A]PP\tnext\n");
1026 if(!iterator.next())
1027 return die_("iterator ended early\n");
1028 our_current_position++;
1030 printf("SVAA[P]P\tnext\n");
1031 if(!iterator.next())
1032 return die_("iterator ended early\n");
1033 our_current_position++;
1035 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1036 padding->set_length(5);
1037 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1038 return die_("copying object");
1039 if(!iterator.set_block(padding, false))
1040 return die_ss_("iterator.set_block(padding, false)", iterator);
1042 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1045 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1046 app->set_id((const unsigned char *)"kuh"); /* twiddle the id */
1047 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1048 return die_("copying object");
1049 if(!iterator.set_block(app, false))
1050 return die_ss_("iterator.set_block(app, false)", iterator);
1052 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1055 printf("SVAAP[A]\tset PADDING (equal)\n");
1056 padding->set_length(27);
1057 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1058 return die_("copying object");
1059 if(!iterator.set_block(padding, false))
1060 return die_ss_("iterator.set_block(padding, false)", iterator);
1062 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1065 printf("SVAAP[P]\tprev\n");
1066 if(!iterator.prev())
1067 return die_("iterator ended early\n");
1068 our_current_position--;
1070 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1071 if(!iterator.delete_block(false))
1072 return die_ss_("iterator.delete_block(false)", iterator);
1073 delete_from_our_metadata_(our_current_position--);
1075 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1078 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1079 if(!iterator.delete_block(false))
1080 return die_ss_("iterator.delete_block(false)", iterator);
1081 delete_from_our_metadata_(our_current_position--);
1083 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1086 printf("SV[A]P\tnext\n");
1087 if(!iterator.next())
1088 return die_("iterator ended early\n");
1089 our_current_position++;
1091 printf("SVA[P]\tinsert PADDING after\n");
1092 padding->set_length(5);
1093 if(!iterator.insert_block_after(padding, false))
1094 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1095 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1098 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1101 printf("SVAP[P]\tprev\n");
1102 if(!iterator.prev())
1103 return die_("iterator ended early\n");
1104 our_current_position--;
1106 printf("SVA[P]P\tprev\n");
1107 if(!iterator.prev())
1108 return die_("iterator ended early\n");
1109 our_current_position--;
1111 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1112 if(!app->set_data(data, 32, true))
1113 return die_("setting APPLICATION data");
1114 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1115 return die_("copying object");
1116 if(!iterator.set_block(app, true))
1117 return die_ss_("iterator.set_block(app, true)", iterator);
1119 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1122 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1123 if(!app->set_data(data, 60, true))
1124 return die_("setting APPLICATION data");
1125 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1126 return die_("copying object");
1127 if(!iterator.set_block(app, true))
1128 return die_ss_("iterator.set_block(app, true)", iterator);
1130 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1133 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1134 if(!app->set_data(data, 87, true))
1135 return die_("setting APPLICATION data");
1136 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1137 return die_("copying object");
1138 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1139 if(!iterator.set_block(app, true))
1140 return die_ss_("iterator.set_block(app, true)", iterator);
1142 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1145 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1146 if(!app->set_data(data, 91, true))
1147 return die_("setting APPLICATION data");
1148 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1149 return die_("copying object");
1150 delete_from_our_metadata_(our_current_position+1);
1151 if(!iterator.set_block(app, true))
1152 return die_ss_("iterator.set_block(app, true)", iterator);
1154 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1157 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1158 if(!app->set_data(data, 100, true))
1159 return die_("setting APPLICATION data");
1160 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1161 return die_("copying object");
1162 delete_from_our_metadata_(our_current_position+1);
1163 our_metadata_.blocks[our_current_position]->set_is_last(true);
1164 if(!iterator.set_block(app, true))
1165 return die_ss_("iterator.set_block(app, true)", iterator);
1167 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1170 printf("SV[A]\tset PADDING (equal size)\n");
1171 padding->set_length(app->get_length());
1172 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1173 return die_("copying object");
1174 if(!iterator.set_block(padding, true))
1175 return die_ss_("iterator.set_block(padding, true)", iterator);
1177 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1180 printf("SV[P]\tinsert PADDING after\n");
1181 if(!iterator.insert_block_after(padding, false))
1182 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1183 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1186 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1189 printf("SVP[P]\tinsert PADDING after\n");
1190 padding->set_length(5);
1191 if(!iterator.insert_block_after(padding, false))
1192 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1193 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1196 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1199 printf("SVPP[P]\tprev\n");
1200 if(!iterator.prev())
1201 return die_("iterator ended early\n");
1202 our_current_position--;
1204 printf("SVP[P]P\tprev\n");
1205 if(!iterator.prev())
1206 return die_("iterator ended early\n");
1207 our_current_position--;
1209 printf("SV[P]PP\tprev\n");
1210 if(!iterator.prev())
1211 return die_("iterator ended early\n");
1212 our_current_position--;
1214 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1215 if(!app->set_data(data, 101, true))
1216 return die_("setting APPLICATION data");
1217 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1218 return die_("copying object");
1219 if(!iterator.insert_block_after(app, true))
1220 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1222 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1225 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1226 if(!iterator.delete_block(false))
1227 return die_ss_("iterator.delete_block(false)", iterator);
1228 delete_from_our_metadata_(our_current_position--);
1230 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1233 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1234 if(!app->set_data(data, 97, true))
1235 return die_("setting APPLICATION data");
1236 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1237 return die_("copying object");
1238 if(!iterator.insert_block_after(app, true))
1239 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1241 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1244 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1245 if(!iterator.delete_block(false))
1246 return die_ss_("iterator.delete_block(false)", iterator);
1247 delete_from_our_metadata_(our_current_position--);
1249 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1252 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1253 if(!app->set_data(data, 100, true))
1254 return die_("setting APPLICATION data");
1255 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1256 return die_("copying object");
1257 delete_from_our_metadata_(our_current_position+1);
1258 if(!iterator.insert_block_after(app, true))
1259 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1261 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1264 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1265 if(!iterator.delete_block(false))
1266 return die_ss_("iterator.delete_block(false)", iterator);
1267 delete_from_our_metadata_(our_current_position--);
1269 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1272 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1273 if(!app->set_data(data, 96, true))
1274 return die_("setting APPLICATION data");
1275 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1276 return die_("copying object");
1277 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1278 if(!iterator.insert_block_after(app, true))
1279 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1281 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1284 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1285 if(!iterator.delete_block(false))
1286 return die_ss_("iterator.delete_block(false)", iterator);
1287 delete_from_our_metadata_(our_current_position--);
1289 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1292 printf("S[V]PP\tnext\n");
1293 if(!iterator.next())
1294 return die_("iterator ended early\n");
1295 our_current_position++;
1297 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1298 if(!iterator.delete_block(false))
1299 return die_ss_("iterator.delete_block(false)", iterator);
1300 delete_from_our_metadata_(our_current_position--);
1302 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1305 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1306 if(!app->set_data(data, 1, true))
1307 return die_("setting APPLICATION data");
1308 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1309 return die_("copying object");
1310 delete_from_our_metadata_(our_current_position+1);
1311 if(!iterator.insert_block_after(app, true))
1312 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1314 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1321 if(!remove_file_(flacfile_))
1327 static bool test_level_2_(bool filename_based)
1329 FLAC::Metadata::Prototype *block;
1330 FLAC::Metadata::StreamInfo *streaminfo;
1331 FLAC::Metadata::Application *app;
1332 FLAC::Metadata::Padding *padding;
1333 FLAC__byte data[2000];
1334 unsigned our_current_position;
1336 // initialize 'data' to avoid Valgrind errors
1337 memset(data, 0, sizeof(data));
1339 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1341 printf("generate read-only file\n");
1343 if(!generate_file_())
1346 if(!change_stats_(flacfile_, /*read_only=*/true))
1349 printf("create chain\n");
1350 FLAC::Metadata::Chain chain;
1351 if(!chain.is_valid())
1352 return die_("allocating memory for chain");
1354 printf("read chain\n");
1356 if(!read_chain_(chain, flacfile_, filename_based))
1357 return die_c_("reading chain", chain.status());
1359 printf("[S]VP\ttest initial metadata\n");
1361 if(!compare_chain_(chain, 0, 0))
1363 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1366 printf("switch file to read-write\n");
1368 if(!change_stats_(flacfile_, /*read-only=*/false))
1371 printf("create iterator\n");
1373 FLAC::Metadata::Iterator iterator;
1374 if(!iterator.is_valid())
1375 return die_("allocating memory for iterator");
1377 our_current_position = 0;
1379 iterator.init(chain);
1381 if(0 == (block = iterator.get_block()))
1382 return die_("getting block from iterator");
1384 FLAC__ASSERT(block->get_type() == FLAC__METADATA_TYPE_STREAMINFO);
1386 printf("[S]VP\tmodify STREAMINFO, write\n");
1388 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
1389 FLAC__ASSERT(0 != streaminfo);
1390 streaminfo->set_sample_rate(32000);
1391 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1392 return die_("copying object");
1395 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1396 return die_c_("during chain.write(false, true)", chain.status());
1397 block = iterator.get_block();
1398 if(!compare_chain_(chain, our_current_position, block))
1401 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1404 printf("[S]VP\tnext\n");
1405 if(!iterator.next())
1406 return die_("iterator ended early\n");
1407 our_current_position++;
1409 printf("S[V]P\tnext\n");
1410 if(!iterator.next())
1411 return die_("iterator ended early\n");
1412 our_current_position++;
1414 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1415 if(0 == (block = iterator.get_block()))
1416 return die_("getting block from iterator");
1417 if(0 == (app = new FLAC::Metadata::Application()))
1418 return die_("new FLAC::Metadata::Application()");
1419 app->set_id((const unsigned char *)"duh");
1420 if(!app->set_data(data, block->get_length()-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1421 return die_("setting APPLICATION data");
1423 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1424 return die_("copying object");
1425 if(!iterator.set_block(app))
1426 return die_c_("iterator.set_block(app)", chain.status());
1428 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1429 return die_c_("during chain.write(false, false)", chain.status());
1430 block = iterator.get_block();
1431 if(!compare_chain_(chain, our_current_position, block))
1434 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1437 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1438 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1439 return die_("copying object");
1440 if(!app->set_data(data, 26, true))
1441 return die_("setting APPLICATION data");
1442 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1443 return die_("copying object");
1444 if(!iterator.set_block(app))
1445 return die_c_("iterator.set_block(app)", chain.status());
1447 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1448 return die_c_("during chain.write(false, false)", chain.status());
1449 block = iterator.get_block();
1450 if(!compare_chain_(chain, our_current_position, block))
1453 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1456 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1457 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1458 return die_("copying object");
1459 if(!app->set_data(data, 28, true))
1460 return die_("setting APPLICATION data");
1461 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1462 return die_("copying object");
1463 if(!iterator.set_block(app))
1464 return die_c_("iterator.set_block(app)", chain.status());
1466 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1467 return die_c_("during chain.write(false, false)", chain.status());
1468 block = iterator.get_block();
1469 if(!compare_chain_(chain, our_current_position, block))
1472 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1475 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1476 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1477 return die_("copying object");
1478 if(!app->set_data(data, 36, true))
1479 return die_("setting APPLICATION data");
1480 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1481 return die_("copying object");
1482 if(!iterator.set_block(app))
1483 return die_c_("iterator.set_block(app)", chain.status());
1485 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1486 return die_c_("during chain.write(false, false)", chain.status());
1487 block = iterator.get_block();
1488 if(!compare_chain_(chain, our_current_position, block))
1491 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1494 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1495 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1496 return die_("copying object");
1497 if(!app->set_data(data, 33, true))
1498 return die_("setting APPLICATION data");
1499 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1500 return die_("copying object");
1501 if(!iterator.set_block(app))
1502 return die_c_("iterator.set_block(app)", chain.status());
1504 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1505 return die_c_("during chain.write(true, false)", chain.status());
1506 block = iterator.get_block();
1507 if(!compare_chain_(chain, our_current_position, block))
1510 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1513 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1514 if(0 == (padding = new FLAC::Metadata::Padding()))
1515 return die_("creating PADDING block");
1516 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1517 return die_("copying object");
1518 if(!app->set_data(data, 29, true))
1519 return die_("setting APPLICATION data");
1520 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1521 return die_("copying object");
1522 padding->set_length(0);
1523 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1524 return die_("internal error");
1525 if(!iterator.set_block(app))
1526 return die_c_("iterator.set_block(app)", chain.status());
1528 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1529 return die_c_("during chain.write(true, false)", chain.status());
1530 block = iterator.get_block();
1531 if(!compare_chain_(chain, our_current_position, block))
1534 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1537 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1538 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1539 return die_("copying object");
1540 if(!app->set_data(data, 16, true))
1541 return die_("setting APPLICATION data");
1542 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1543 return die_("copying object");
1544 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(13);
1545 if(!iterator.set_block(app))
1546 return die_c_("iterator.set_block(app)", chain.status());
1548 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1549 return die_c_("during chain.write(true, false)", chain.status());
1550 block = iterator.get_block();
1551 if(!compare_chain_(chain, our_current_position, block))
1554 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1557 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1558 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1559 return die_("copying object");
1560 if(!app->set_data(data, 50, true))
1561 return die_("setting APPLICATION data");
1562 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1563 return die_("copying object");
1564 if(!iterator.set_block(app))
1565 return die_c_("iterator.set_block(app)", chain.status());
1567 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1568 return die_c_("during chain.write(true, false)", chain.status());
1569 block = iterator.get_block();
1570 if(!compare_chain_(chain, our_current_position, block))
1573 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1576 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1577 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1578 return die_("copying object");
1579 if(!app->set_data(data, 56, true))
1580 return die_("setting APPLICATION data");
1581 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1582 return die_("copying object");
1583 add_to_padding_length_(our_current_position+1, -(56 - 50));
1584 if(!iterator.set_block(app))
1585 return die_c_("iterator.set_block(app)", chain.status());
1587 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1588 return die_c_("during chain.write(true, false)", chain.status());
1589 block = iterator.get_block();
1590 if(!compare_chain_(chain, our_current_position, block))
1593 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1596 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1597 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1598 return die_("copying object");
1599 if(!app->set_data(data, 67, true))
1600 return die_("setting APPLICATION data");
1601 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1602 return die_("copying object");
1603 delete_from_our_metadata_(our_current_position+1);
1604 if(!iterator.set_block(app))
1605 return die_c_("iterator.set_block(app)", chain.status());
1607 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1608 return die_c_("during chain.write(true, false)", chain.status());
1609 block = iterator.get_block();
1610 if(!compare_chain_(chain, our_current_position, block))
1613 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1616 printf("SV[A]\tprev\n");
1617 if(!iterator.prev())
1618 return die_("iterator ended early\n");
1619 our_current_position--;
1621 printf("S[V]A\tprev\n");
1622 if(!iterator.prev())
1623 return die_("iterator ended early\n");
1624 our_current_position--;
1626 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1627 if(0 == (padding = new FLAC::Metadata::Padding()))
1628 return die_("creating PADDING block");
1629 padding->set_length(30);
1630 if(!iterator.insert_block_before(padding))
1631 printf("\titerator.insert_block_before() returned false like it should\n");
1633 return die_("iterator.insert_block_before() should have returned false");
1635 printf("[S]VA\tnext\n");
1636 if(!iterator.next())
1637 return die_("iterator ended early\n");
1638 our_current_position++;
1640 printf("S[V]A\tinsert PADDING after\n");
1641 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1642 return die_("copying metadata");
1643 if(!iterator.insert_block_after(padding))
1644 return die_("iterator.insert_block_after(padding)");
1646 block = iterator.get_block();
1647 if(!compare_chain_(chain, our_current_position, block))
1651 printf("SV[P]A\tinsert PADDING before\n");
1652 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1653 return die_("creating PADDING block");
1654 padding->set_length(17);
1655 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1656 return die_("copying metadata");
1657 if(!iterator.insert_block_before(padding))
1658 return die_("iterator.insert_block_before(padding)");
1660 block = iterator.get_block();
1661 if(!compare_chain_(chain, our_current_position, block))
1665 printf("SV[P]PA\tinsert PADDING before\n");
1666 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1667 return die_("creating PADDING block");
1668 padding->set_length(0);
1669 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1670 return die_("copying metadata");
1671 if(!iterator.insert_block_before(padding))
1672 return die_("iterator.insert_block_before(padding)");
1674 block = iterator.get_block();
1675 if(!compare_chain_(chain, our_current_position, block))
1679 printf("SV[P]PPA\tnext\n");
1680 if(!iterator.next())
1681 return die_("iterator ended early\n");
1682 our_current_position++;
1684 printf("SVP[P]PA\tnext\n");
1685 if(!iterator.next())
1686 return die_("iterator ended early\n");
1687 our_current_position++;
1689 printf("SVPP[P]A\tnext\n");
1690 if(!iterator.next())
1691 return die_("iterator ended early\n");
1692 our_current_position++;
1694 printf("SVPPP[A]\tinsert PADDING after\n");
1695 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1696 return die_("creating PADDING block");
1697 padding->set_length(57);
1698 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1699 return die_("copying metadata");
1700 if(!iterator.insert_block_after(padding))
1701 return die_("iterator.insert_block_after(padding)");
1703 block = iterator.get_block();
1704 if(!compare_chain_(chain, our_current_position, block))
1708 printf("SVPPPA[P]\tinsert PADDING before\n");
1709 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1710 return die_("creating PADDING block");
1711 padding->set_length(99);
1712 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1713 return die_("copying metadata");
1714 if(!iterator.insert_block_before(padding))
1715 return die_("iterator.insert_block_before(padding)");
1717 block = iterator.get_block();
1718 if(!compare_chain_(chain, our_current_position, block))
1723 our_current_position = 0;
1725 printf("SVPPPAPP\tmerge padding\n");
1726 chain.merge_padding();
1727 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->get_length());
1728 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->get_length());
1729 add_to_padding_length_(6, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->get_length());
1730 delete_from_our_metadata_(7);
1731 delete_from_our_metadata_(4);
1732 delete_from_our_metadata_(3);
1734 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1735 return die_c_("during chain.write(true, false)", chain.status());
1736 if(!compare_chain_(chain, 0, 0))
1738 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1741 printf("SVPAP\tsort padding\n");
1742 chain.sort_padding();
1743 add_to_padding_length_(4, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->get_length());
1744 delete_from_our_metadata_(2);
1746 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1747 return die_c_("during chain.write(true, false)", chain.status());
1748 if(!compare_chain_(chain, 0, 0))
1750 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1753 printf("create iterator\n");
1755 FLAC::Metadata::Iterator iterator;
1756 if(!iterator.is_valid())
1757 return die_("allocating memory for iterator");
1759 our_current_position = 0;
1761 iterator.init(chain);
1763 printf("[S]VAP\tnext\n");
1764 if(!iterator.next())
1765 return die_("iterator ended early\n");
1766 our_current_position++;
1768 printf("S[V]AP\tnext\n");
1769 if(!iterator.next())
1770 return die_("iterator ended early\n");
1771 our_current_position++;
1773 printf("SV[A]P\tdelete middle block, replace with padding\n");
1774 if(0 == (padding = new FLAC::Metadata::Padding()))
1775 return die_("creating PADDING block");
1776 padding->set_length(71);
1777 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1778 return die_("copying object");
1779 if(!iterator.delete_block(/*replace_with_padding=*/true))
1780 return die_c_("iterator.delete_block(true)", chain.status());
1782 block = iterator.get_block();
1783 if(!compare_chain_(chain, our_current_position, block))
1787 printf("S[V]PP\tnext\n");
1788 if(!iterator.next())
1789 return die_("iterator ended early\n");
1790 our_current_position++;
1792 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1793 delete_from_our_metadata_(our_current_position--);
1794 if(!iterator.delete_block(/*replace_with_padding=*/false))
1795 return die_c_("iterator.delete_block(false)", chain.status());
1797 block = iterator.get_block();
1798 if(!compare_chain_(chain, our_current_position, block))
1802 printf("S[V]P\tnext\n");
1803 if(!iterator.next())
1804 return die_("iterator ended early\n");
1805 our_current_position++;
1807 printf("SV[P]\tdelete last block, replace with padding\n");
1808 if(0 == (padding = new FLAC::Metadata::Padding()))
1809 return die_("creating PADDING block");
1810 padding->set_length(219);
1811 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1812 return die_("copying object");
1813 if(!iterator.delete_block(/*replace_with_padding=*/true))
1814 return die_c_("iterator.delete_block(true)", chain.status());
1816 block = iterator.get_block();
1817 if(!compare_chain_(chain, our_current_position, block))
1821 printf("S[V]P\tnext\n");
1822 if(!iterator.next())
1823 return die_("iterator ended early\n");
1824 our_current_position++;
1826 printf("SV[P]\tdelete last block, don't replace with padding\n");
1827 delete_from_our_metadata_(our_current_position--);
1828 if(!iterator.delete_block(/*replace_with_padding=*/false))
1829 return die_c_("iterator.delete_block(false)", chain.status());
1831 block = iterator.get_block();
1832 if(!compare_chain_(chain, our_current_position, block))
1836 printf("S[V]\tprev\n");
1837 if(!iterator.prev())
1838 return die_("iterator ended early\n");
1839 our_current_position--;
1841 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1842 if(iterator.delete_block(/*replace_with_padding=*/false))
1843 return die_("iterator.delete_block() on STREAMINFO should have failed but didn't");
1845 block = iterator.get_block();
1846 if(!compare_chain_(chain, our_current_position, block))
1850 } // delete iterator
1851 our_current_position = 0;
1853 printf("SV\tmerge padding\n");
1854 chain.merge_padding();
1856 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1857 return die_c_("during chain.write(false, false)", chain.status());
1858 if(!compare_chain_(chain, 0, 0))
1860 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1863 printf("SV\tsort padding\n");
1864 chain.sort_padding();
1866 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1867 return die_c_("during chain.write(false, false)", chain.status());
1868 if(!compare_chain_(chain, 0, 0))
1870 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1873 if(!remove_file_(flacfile_))
1879 static bool test_level_2_misc_()
1881 ::FLAC__IOCallbacks callbacks;
1883 memset(&callbacks, 0, sizeof(callbacks));
1884 callbacks.read = (::FLAC__IOCallback_Read)fread;
1885 #ifdef FLAC__VALGRIND_TESTING
1886 callbacks.write = chain_write_cb_;
1888 callbacks.write = (::FLAC__IOCallback_Write)fwrite;
1890 callbacks.seek = chain_seek_cb_;
1891 callbacks.tell = chain_tell_cb_;
1892 callbacks.eof = chain_eof_cb_;
1894 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1896 printf("generate file\n");
1898 if(!generate_file_())
1901 printf("create chain\n");
1902 FLAC::Metadata::Chain chain;
1903 if(!chain.is_valid())
1904 return die_("allocating chain");
1906 printf("read chain (filename-based)\n");
1908 if(!chain.read(flacfile_))
1909 return die_c_("reading chain", chain.status());
1911 printf("write chain with wrong method Chain::write(with callbacks)\n");
1913 if(chain.write(/*use_padding=*/false, 0, callbacks))
1914 return die_c_("mismatched write should have failed", chain.status());
1915 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1916 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1917 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1920 printf("read chain (filename-based)\n");
1922 if(!chain.read(flacfile_))
1923 return die_c_("reading chain", chain.status());
1925 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
1927 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
1928 return die_c_("mismatched write should have failed", chain.status());
1929 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1930 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1931 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1934 printf("read chain (callback-based)\n");
1936 FILE *file = fopen(flacfile_, "rb");
1938 return die_("opening file");
1939 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1941 return die_c_("reading chain", chain.status());
1946 printf("write chain with wrong method write()\n");
1948 if(chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false))
1949 return die_c_("mismatched write should have failed", chain.status());
1950 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1951 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
1952 printf(" OK: write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1955 printf("read chain (callback-based)\n");
1957 FILE *file = fopen(flacfile_, "rb");
1959 return die_("opening file");
1960 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1962 return die_c_("reading chain", chain.status());
1967 printf("testing Chain::check_if_tempfile_needed()... ");
1969 if(!chain.check_if_tempfile_needed(/*use_padding=*/false))
1970 printf("OK: Chain::check_if_tempfile_needed() returned false like it should\n");
1972 return die_("Chain::check_if_tempfile_needed() returned true but shouldn't have");
1974 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
1976 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
1977 return die_c_("mismatched write should have failed", chain.status());
1978 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1979 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
1980 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1983 printf("read chain (callback-based)\n");
1985 FILE *file = fopen(flacfile_, "rb");
1987 return die_("opening file");
1988 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
1990 return die_c_("reading chain", chain.status());
1995 printf("create iterator\n");
1997 FLAC::Metadata::Iterator iterator;
1998 if(!iterator.is_valid())
1999 return die_("allocating memory for iterator");
2001 iterator.init(chain);
2003 printf("[S]VP\tnext\n");
2004 if(!iterator.next())
2005 return die_("iterator ended early\n");
2007 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2008 if(!iterator.delete_block(/*replace_with_padding=*/false))
2009 return die_c_("block delete failed\n", chain.status());
2011 printf("testing Chain::check_if_tempfile_needed()... ");
2013 if(chain.check_if_tempfile_needed(/*use_padding=*/false))
2014 printf("OK: Chain::check_if_tempfile_needed() returned true like it should\n");
2016 return die_("Chain::check_if_tempfile_needed() returned false but shouldn't have");
2018 printf("write chain with wrong method Chain::write(with callbacks)\n");
2020 if(chain.write(/*use_padding=*/false, 0, callbacks))
2021 return die_c_("mismatched write should have failed", chain.status());
2022 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2023 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
2024 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2027 } // delete iterator
2029 if(!remove_file_(flacfile_))
2035 bool test_metadata_file_manipulation()
2037 printf("\n+++ libFLAC++ unit test: metadata manipulation\n\n");
2039 our_metadata_.num_blocks = 0;
2041 if(!test_level_0_())
2044 if(!test_level_1_())
2047 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2049 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2051 if(!test_level_2_misc_())