1 /* test_libFLAC++ - Unit tester for libFLAC++
2 * Copyright (C) 2002,2003,2004,2005,2006 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 <stdlib.h> /* for malloc() */
21 #include <string.h> /* for memcpy()/memset() */
22 #if defined _MSC_VER || defined __MINGW32__
23 #include <sys/utime.h> /* for utime() */
24 #include <io.h> /* for chmod() */
25 //@@@ [2G limit] hacks for MSVC6
29 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
30 #include <utime.h> /* for utime() */
31 #include <unistd.h> /* for chown(), unlink() */
33 #include <sys/stat.h> /* for stat(), maybe chmod() */
34 #include "FLAC/assert.h"
35 #include "FLAC++/decoder.h"
36 #include "FLAC++/metadata.h"
37 #include "share/grabbag.h"
39 #include "test_libs_common/file_utils_flac.h"
42 /******************************************************************************
43 The general strategy of these tests (for interface levels 1 and 2) is
44 to create a dummy FLAC file with a known set of initial metadata
45 blocks, then keep a mirror locally of what we expect the metadata to be
46 after each operation. Then testing becomes a simple matter of running
47 a FLAC::Decoder::File over the dummy file after each operation, comparing
48 the decoded metadata to what's in our local copy. If there are any
49 differences in the metadata, or the actual audio data is corrupted, we
50 will catch it while decoding.
51 ******************************************************************************/
53 class OurFileDecoder: public FLAC::Decoder::File {
55 inline OurFileDecoder(bool ignore_metadata): ignore_metadata_(ignore_metadata), error_occurred_(false) { }
57 bool ignore_metadata_;
60 ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
61 void metadata_callback(const ::FLAC__StreamMetadata *metadata);
62 void error_callback(::FLAC__StreamDecoderErrorStatus status);
66 FLAC::Metadata::Prototype *blocks[64];
70 static const char *flacfile_ = "metadata.flac";
72 /* our copy of the metadata in flacfile_ */
73 static OurMetadata our_metadata_;
75 /* the current block number that corresponds to the position of the iterator we are testing */
76 static unsigned mc_our_block_number_ = 0;
78 static bool die_(const char *msg)
80 printf("ERROR: %s\n", msg);
84 static bool die_c_(const char *msg, FLAC::Metadata::Chain::Status status)
86 printf("ERROR: %s\n", msg);
87 printf(" status=%u (%s)\n", (unsigned)((::FLAC__Metadata_ChainStatus)status), status.as_cstring());
91 static bool die_ss_(const char *msg, FLAC::Metadata::SimpleIterator &iterator)
93 const FLAC::Metadata::SimpleIterator::Status status = iterator.status();
94 printf("ERROR: %s\n", msg);
95 printf(" status=%u (%s)\n", (unsigned)((::FLAC__Metadata_SimpleIteratorStatus)status), status.as_cstring());
99 static void *malloc_or_die_(size_t size)
101 void *x = malloc(size);
103 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
109 static char *strdup_or_die_(const char *s)
113 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
119 /* functions for working with our metadata copy */
121 static bool replace_in_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
124 FLAC::Metadata::Prototype *obj = block;
125 FLAC__ASSERT(position < our_metadata_.num_blocks);
127 if(0 == (obj = FLAC::Metadata::clone(block)))
128 return die_("during FLAC::Metadata::clone()");
130 delete our_metadata_.blocks[position];
131 our_metadata_.blocks[position] = obj;
133 /* set the is_last flags */
134 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
135 our_metadata_.blocks[i]->set_is_last(false);
136 our_metadata_.blocks[i]->set_is_last(true);
141 static bool insert_to_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
144 FLAC::Metadata::Prototype *obj = block;
146 if(0 == (obj = FLAC::Metadata::clone(block)))
147 return die_("during FLAC::Metadata::clone()");
149 if(position > our_metadata_.num_blocks) {
150 position = our_metadata_.num_blocks;
153 for(i = our_metadata_.num_blocks; i > position; i--)
154 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
156 our_metadata_.blocks[position] = obj;
157 our_metadata_.num_blocks++;
159 /* set the is_last flags */
160 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
161 our_metadata_.blocks[i]->set_is_last(false);
162 our_metadata_.blocks[i]->set_is_last(true);
167 static void delete_from_our_metadata_(unsigned position)
170 FLAC__ASSERT(position < our_metadata_.num_blocks);
171 delete our_metadata_.blocks[position];
172 for(i = position; i < our_metadata_.num_blocks - 1; i++)
173 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
174 our_metadata_.num_blocks--;
176 /* set the is_last flags */
177 if(our_metadata_.num_blocks > 0) {
178 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
179 our_metadata_.blocks[i]->set_is_last(false);
180 our_metadata_.blocks[i]->set_is_last(true);
184 void add_to_padding_length_(unsigned index, int delta)
186 FLAC::Metadata::Padding *padding = dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[index]);
187 FLAC__ASSERT(0 != padding);
188 padding->set_length((unsigned)((int)padding->get_length() + delta));
192 * This wad of functions supports filename- and callback-based chain reading/writing.
193 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
195 bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
197 static const char *tempfile_suffix = ".metadata_edit";
199 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
201 strcpy(*tempfilename, filename);
202 strcat(*tempfilename, tempfile_suffix);
204 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
210 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
213 (void)fclose(*tempfile);
217 if(0 != *tempfilename) {
218 (void)unlink(*tempfilename);
224 bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
226 FLAC__ASSERT(0 != filename);
227 FLAC__ASSERT(0 != tempfile);
228 FLAC__ASSERT(0 != tempfilename);
229 FLAC__ASSERT(0 != *tempfilename);
232 (void)fclose(*tempfile);
236 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
237 /* on some flavors of windows, rename() will fail if the destination already exists */
238 if(unlink(filename) < 0) {
239 cleanup_tempfile_(tempfile, tempfilename);
244 if(0 != rename(*tempfilename, filename)) {
245 cleanup_tempfile_(tempfile, tempfilename);
249 cleanup_tempfile_(tempfile, tempfilename);
254 bool get_file_stats_(const char *filename, struct stat *stats)
256 FLAC__ASSERT(0 != filename);
257 FLAC__ASSERT(0 != stats);
258 return (0 == stat(filename, stats));
261 void set_file_stats_(const char *filename, struct stat *stats)
263 struct utimbuf srctime;
265 FLAC__ASSERT(0 != filename);
266 FLAC__ASSERT(0 != stats);
268 srctime.actime = stats->st_atime;
269 srctime.modtime = stats->st_mtime;
270 (void)chmod(filename, stats->st_mode);
271 (void)utime(filename, &srctime);
272 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
273 (void)chown(filename, stats->st_uid, (gid_t)(-1));
274 (void)chown(filename, (uid_t)(-1), stats->st_gid);
278 #ifdef FLAC__VALGRIND_TESTING
279 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, ::FLAC__IOHandle handle)
281 FILE *stream = (FILE*)handle;
282 size_t ret = fwrite(ptr, size, nmemb, stream);
289 static int chain_seek_cb_(::FLAC__IOHandle handle, FLAC__int64 offset, int whence)
291 off_t o = (off_t)offset;
292 FLAC__ASSERT(offset == o);
293 return fseeko((FILE*)handle, o, whence);
296 static FLAC__int64 chain_tell_cb_(::FLAC__IOHandle handle)
298 return ftello((FILE*)handle);
301 static int chain_eof_cb_(::FLAC__IOHandle handle)
303 return feof((FILE*)handle);
306 static bool write_chain_(FLAC::Metadata::Chain &chain, bool use_padding, bool preserve_file_stats, bool filename_based, const char *filename)
309 return chain.write(use_padding, preserve_file_stats);
311 ::FLAC__IOCallbacks callbacks;
313 memset(&callbacks, 0, sizeof(callbacks));
314 callbacks.read = (::FLAC__IOCallback_Read)fread;
315 #ifdef FLAC__VALGRIND_TESTING
316 callbacks.write = chain_write_cb_;
318 callbacks.write = (::FLAC__IOCallback_Write)fwrite;
320 callbacks.seek = chain_seek_cb_;
321 callbacks.eof = chain_eof_cb_;
323 if(chain.check_if_tempfile_needed(use_padding)) {
325 FILE *file, *tempfile;
327 if(preserve_file_stats) {
328 if(!get_file_stats_(filename, &stats))
331 if(0 == (file = fopen(filename, "rb")))
332 return false; /*@@@ chain status still says OK though */
333 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
335 cleanup_tempfile_(&tempfile, &tempfilename);
336 return false; /*@@@ chain status still says OK though */
338 if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks, (::FLAC__IOHandle)tempfile, callbacks)) {
346 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
348 if(preserve_file_stats)
349 set_file_stats_(filename, &stats);
352 FILE *file = fopen(filename, "r+b");
354 return false; /*@@@ chain status still says OK though */
355 if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks))
364 static bool read_chain_(FLAC::Metadata::Chain &chain, const char *filename, bool filename_based)
367 return chain.read(filename);
369 ::FLAC__IOCallbacks callbacks;
371 memset(&callbacks, 0, sizeof(callbacks));
372 callbacks.read = (::FLAC__IOCallback_Read)fread;
373 callbacks.seek = chain_seek_cb_;
374 callbacks.tell = chain_tell_cb_;
378 FILE *file = fopen(filename, "rb");
380 return false; /*@@@ chain status still says OK though */
381 ret = chain.read((::FLAC__IOHandle)file, callbacks);
388 /* function for comparing our metadata to a FLAC::Metadata::Chain */
390 static bool compare_chain_(FLAC::Metadata::Chain &chain, unsigned current_position, FLAC::Metadata::Prototype *current_block)
393 FLAC::Metadata::Iterator iterator;
396 printf("\tcomparing chain... ");
399 if(!iterator.is_valid())
400 return die_("allocating memory for iterator");
402 iterator.init(chain);
406 FLAC::Metadata::Prototype *block;
411 if(0 == (block = iterator.get_block()))
412 return die_("getting block from iterator");
414 if(*block != *our_metadata_.blocks[i])
415 return die_("metadata block mismatch");
419 next_ok = iterator.next();
420 } while(i < our_metadata_.num_blocks && next_ok);
423 return die_("chain has more blocks than expected");
425 if(i < our_metadata_.num_blocks)
426 return die_("short block count in chain");
428 if(0 != current_block) {
429 printf("CURRENT_POSITION... ");
432 if(*current_block != *our_metadata_.blocks[current_position])
433 return die_("metadata block mismatch");
441 ::FLAC__StreamDecoderWriteStatus OurFileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
446 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
447 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
449 printf("content... ");
453 return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
456 void OurFileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
458 /* don't bother checking if we've already hit an error */
462 printf("%d... ", mc_our_block_number_);
465 if(!ignore_metadata_) {
466 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
467 (void)die_("got more metadata blocks than expected");
468 error_occurred_ = true;
471 if(*our_metadata_.blocks[mc_our_block_number_] != metadata) {
472 (void)die_("metadata block mismatch");
473 error_occurred_ = true;
478 mc_our_block_number_++;
481 void OurFileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
483 error_occurred_ = true;
484 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
487 static bool generate_file_(FLAC__bool include_extras)
489 ::FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
490 ::FLAC__StreamMetadata *metadata[4];
491 unsigned i = 0, n = 0;
493 printf("generating FLAC file for test\n");
495 while(our_metadata_.num_blocks > 0)
496 delete_from_our_metadata_(0);
498 streaminfo.is_last = false;
499 streaminfo.type = ::FLAC__METADATA_TYPE_STREAMINFO;
500 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
501 streaminfo.data.stream_info.min_blocksize = 576;
502 streaminfo.data.stream_info.max_blocksize = 576;
503 streaminfo.data.stream_info.min_framesize = 0;
504 streaminfo.data.stream_info.max_framesize = 0;
505 streaminfo.data.stream_info.sample_rate = 44100;
506 streaminfo.data.stream_info.channels = 1;
507 streaminfo.data.stream_info.bits_per_sample = 8;
508 streaminfo.data.stream_info.total_samples = 0;
509 memset(streaminfo.data.stream_info.md5sum, 0, 16);
512 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
513 vorbiscomment.is_last = false;
514 vorbiscomment.type = ::FLAC__METADATA_TYPE_VORBIS_COMMENT;
515 vorbiscomment.length = (4 + vendor_string_length) + 4;
516 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
517 vorbiscomment.data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
518 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
519 vorbiscomment.data.vorbis_comment.num_comments = 0;
520 vorbiscomment.data.vorbis_comment.comments = 0;
524 if (0 == (cuesheet = ::FLAC__metadata_object_new(::FLAC__METADATA_TYPE_CUESHEET)))
525 return die_("priming our metadata");
526 cuesheet->is_last = false;
527 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
528 cuesheet->data.cue_sheet.lead_in = 123;
529 cuesheet->data.cue_sheet.is_cd = false;
530 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
531 return die_("priming our metadata");
532 cuesheet->data.cue_sheet.tracks[0].number = 1;
533 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
534 return die_("priming our metadata");
538 picture.is_last = false;
539 picture.type = ::FLAC__METADATA_TYPE_PICTURE;
542 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
543 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
544 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
545 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
546 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
547 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
548 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
549 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
552 picture.data.picture.type = ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
553 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
554 picture.length += strlen(picture.data.picture.mime_type);
555 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
556 picture.length += strlen((const char *)picture.data.picture.description);
557 picture.data.picture.width = 300;
558 picture.data.picture.height = 300;
559 picture.data.picture.depth = 24;
560 picture.data.picture.colors = 0;
561 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
562 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
563 picture.length += picture.data.picture.data_length;
566 padding.is_last = true;
567 padding.type = ::FLAC__METADATA_TYPE_PADDING;
568 padding.length = 1234;
570 metadata[n++] = &vorbiscomment;
572 metadata[n++] = cuesheet;
573 metadata[n++] = &picture;
575 metadata[n++] = &padding;
577 FLAC::Metadata::StreamInfo s(&streaminfo);
578 FLAC::Metadata::VorbisComment v(&vorbiscomment);
579 FLAC::Metadata::CueSheet c(cuesheet, /*copy=*/false);
580 FLAC::Metadata::Picture pi(&picture);
581 FLAC::Metadata::Padding p(&padding);
583 !insert_to_our_metadata_(&s, i++, /*copy=*/true) ||
584 !insert_to_our_metadata_(&v, i++, /*copy=*/true) ||
585 (include_extras && !insert_to_our_metadata_(&c, i++, /*copy=*/true)) ||
586 (include_extras && !insert_to_our_metadata_(&pi, i++, /*copy=*/true)) ||
587 !insert_to_our_metadata_(&p, i++, /*copy=*/true)
589 return die_("priming our metadata");
591 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
592 return die_("creating the encoded file");
594 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
599 static bool test_file_(const char *filename, bool ignore_metadata)
601 OurFileDecoder decoder(ignore_metadata);
603 FLAC__ASSERT(0 != filename);
605 mc_our_block_number_ = 0;
606 decoder.error_occurred_ = false;
608 printf("\ttesting '%s'... ", filename);
611 if(!decoder.is_valid())
612 return die_("couldn't allocate decoder instance");
614 decoder.set_md5_checking(true);
615 decoder.set_metadata_respond_all();
616 if(decoder.init(filename) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK) {
618 return die_("initializing decoder\n");
620 if(!decoder.process_until_end_of_stream()) {
622 return die_("decoding file\n");
627 if(decoder.error_occurred_)
630 if(mc_our_block_number_ != our_metadata_.num_blocks)
631 return die_("short metadata block count");
637 static bool change_stats_(const char *filename, bool read_only)
639 if(!grabbag__file_change_stats(filename, read_only))
640 return die_("during grabbag__file_change_stats()");
645 static bool remove_file_(const char *filename)
647 while(our_metadata_.num_blocks > 0)
648 delete_from_our_metadata_(0);
650 if(!grabbag__file_remove_file(filename))
651 return die_("removing file");
656 static bool test_level_0_()
658 FLAC::Metadata::StreamInfo streaminfo;
660 printf("\n\n++++++ testing level 0 interface\n");
662 if(!generate_file_(/*include_extras=*/true))
665 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
668 printf("testing FLAC::Metadata::get_streaminfo()... ");
670 if(!FLAC::Metadata::get_streaminfo(flacfile_, streaminfo))
671 return die_("during FLAC::Metadata::get_streaminfo()");
673 /* check to see if some basic data matches (c.f. generate_file_()) */
674 if(streaminfo.get_channels() != 1)
675 return die_("mismatch in streaminfo.get_channels()");
676 if(streaminfo.get_bits_per_sample() != 8)
677 return die_("mismatch in streaminfo.get_bits_per_sample()");
678 if(streaminfo.get_sample_rate() != 44100)
679 return die_("mismatch in streaminfo.get_sample_rate()");
680 if(streaminfo.get_min_blocksize() != 576)
681 return die_("mismatch in streaminfo.get_min_blocksize()");
682 if(streaminfo.get_max_blocksize() != 576)
683 return die_("mismatch in streaminfo.get_max_blocksize()");
688 printf("testing FLAC::Metadata::get_tags(VorbisComment *&)... ");
690 FLAC::Metadata::VorbisComment *tags = 0;
692 if(!FLAC::Metadata::get_tags(flacfile_, tags))
693 return die_("during FLAC::Metadata::get_tags()");
695 /* check to see if some basic data matches (c.f. generate_file_()) */
696 if(tags->get_num_comments() != 0)
697 return die_("mismatch in tags->get_num_comments()");
705 printf("testing FLAC::Metadata::get_tags(VorbisComment &)... ");
707 FLAC::Metadata::VorbisComment tags;
709 if(!FLAC::Metadata::get_tags(flacfile_, tags))
710 return die_("during FLAC::Metadata::get_tags()");
712 /* check to see if some basic data matches (c.f. generate_file_()) */
713 if(tags.get_num_comments() != 0)
714 return die_("mismatch in tags.get_num_comments()");
720 printf("testing FLAC::Metadata::get_cuesheet(CueSheet *&)... ");
722 FLAC::Metadata::CueSheet *cuesheet = 0;
724 if(!FLAC::Metadata::get_cuesheet(flacfile_, cuesheet))
725 return die_("during FLAC::Metadata::get_cuesheet()");
727 /* check to see if some basic data matches (c.f. generate_file_()) */
728 if(cuesheet->get_lead_in() != 123)
729 return die_("mismatch in cuesheet->get_lead_in()");
737 printf("testing FLAC::Metadata::get_cuesheet(CueSheet &)... ");
739 FLAC::Metadata::CueSheet cuesheet;
741 if(!FLAC::Metadata::get_cuesheet(flacfile_, cuesheet))
742 return die_("during FLAC::Metadata::get_cuesheet()");
744 /* check to see if some basic data matches (c.f. generate_file_()) */
745 if(cuesheet.get_lead_in() != 123)
746 return die_("mismatch in cuesheet.get_lead_in()");
752 printf("testing FLAC::Metadata::get_picture(Picture *&)... ");
754 FLAC::Metadata::Picture *picture = 0;
756 if(!FLAC::Metadata::get_picture(flacfile_, picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1), /*max_colors=*/(unsigned)(-1)))
757 return die_("during FLAC::Metadata::get_picture()");
759 /* check to see if some basic data matches (c.f. generate_file_()) */
760 if(picture->get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
761 return die_("mismatch in picture->get_type ()");
769 printf("testing FLAC::Metadata::get_picture(Picture &)... ");
771 FLAC::Metadata::Picture picture;
773 if(!FLAC::Metadata::get_picture(flacfile_, picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1), /*max_colors=*/(unsigned)(-1)))
774 return die_("during FLAC::Metadata::get_picture()");
776 /* check to see if some basic data matches (c.f. generate_file_()) */
777 if(picture.get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
778 return die_("mismatch in picture->get_type ()");
783 if(!remove_file_(flacfile_))
789 static bool test_level_1_()
791 FLAC::Metadata::Prototype *block;
792 FLAC::Metadata::StreamInfo *streaminfo;
793 FLAC::Metadata::Padding *padding;
794 FLAC::Metadata::Application *app;
795 FLAC__byte data[1000];
796 unsigned our_current_position = 0;
798 // initialize 'data' to avoid Valgrind errors
799 memset(data, 0, sizeof(data));
801 printf("\n\n++++++ testing level 1 interface\n");
803 /************************************************************/
805 printf("simple iterator on read-only file\n");
807 if(!generate_file_(/*include_extras=*/false))
810 if(!change_stats_(flacfile_, /*read_only=*/true))
813 if(!test_file_(flacfile_, /*ignore_metadata=*/true))
816 FLAC::Metadata::SimpleIterator iterator;
818 if(!iterator.is_valid())
819 return die_("iterator.is_valid() returned false");
821 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
822 return die_("iterator.init() returned false");
824 printf("is writable = %u\n", (unsigned)iterator.is_writable());
825 if(iterator.is_writable())
826 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
828 printf("iterate forwards\n");
830 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
831 return die_("expected STREAMINFO type from iterator.get_block_type()");
832 if(0 == (block = iterator.get_block()))
833 return die_("getting block 0");
834 if(block->get_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
835 return die_("expected STREAMINFO type");
836 if(block->get_is_last())
837 return die_("expected is_last to be false");
838 if(block->get_length() != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
839 return die_("bad STREAMINFO length");
840 /* check to see if some basic data matches (c.f. generate_file_()) */
841 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
842 FLAC__ASSERT(0 != streaminfo);
843 if(streaminfo->get_channels() != 1)
844 return die_("mismatch in channels");
845 if(streaminfo->get_bits_per_sample() != 8)
846 return die_("mismatch in bits_per_sample");
847 if(streaminfo->get_sample_rate() != 44100)
848 return die_("mismatch in sample_rate");
849 if(streaminfo->get_min_blocksize() != 576)
850 return die_("mismatch in min_blocksize");
851 if(streaminfo->get_max_blocksize() != 576)
852 return die_("mismatch in max_blocksize");
853 // we will delete streaminfo a little later when we're really done with it...
856 return die_("forward iterator ended early");
857 our_current_position++;
860 return die_("forward iterator ended early");
861 our_current_position++;
863 if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_PADDING)
864 return die_("expected PADDING type from iterator.get_block_type()");
865 if(0 == (block = iterator.get_block()))
866 return die_("getting block 1");
867 if(block->get_type() != ::FLAC__METADATA_TYPE_PADDING)
868 return die_("expected PADDING type");
869 if(!block->get_is_last())
870 return die_("expected is_last to be true");
871 /* check to see if some basic data matches (c.f. generate_file_()) */
872 if(block->get_length() != 1234)
873 return die_("bad PADDING length");
877 return die_("forward iterator returned true but should have returned false");
879 printf("iterate backwards\n");
881 return die_("reverse iterator ended early");
883 return die_("reverse iterator ended early");
885 return die_("reverse iterator returned true but should have returned false");
887 printf("testing iterator.set_block() on read-only file...\n");
889 if(!iterator.set_block(streaminfo, false))
890 printf("PASSED. iterator.set_block() returned false like it should\n");
892 return die_("iterator.set_block() returned true but shouldn't have");
896 /************************************************************/
898 printf("simple iterator on writable file\n");
900 if(!change_stats_(flacfile_, /*read-only=*/false))
903 printf("creating APPLICATION block\n");
905 if(0 == (app = new FLAC::Metadata::Application()))
906 return die_("new FLAC::Metadata::Application()");
907 app->set_id((const unsigned char *)"duh");
909 printf("creating PADDING block\n");
911 if(0 == (padding = new FLAC::Metadata::Padding()))
912 return die_("new FLAC::Metadata::Padding()");
913 padding->set_length(20);
915 FLAC::Metadata::SimpleIterator iterator;
917 if(!iterator.is_valid())
918 return die_("iterator.is_valid() returned false");
920 if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
921 return die_("iterator.init() returned false");
922 our_current_position = 0;
924 printf("is writable = %u\n", (unsigned)iterator.is_writable());
926 printf("[S]VP\ttry to write over STREAMINFO block...\n");
927 if(!iterator.set_block(app, false))
928 printf("\titerator.set_block() returned false like it should\n");
930 return die_("iterator.set_block() returned true but shouldn't have");
932 printf("[S]VP\tnext\n");
934 return die_("iterator ended early\n");
935 our_current_position++;
937 printf("S[V]P\tnext\n");
939 return die_("iterator ended early\n");
940 our_current_position++;
942 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
943 padding->set_length(25);
944 if(!iterator.insert_block_after(padding, false))
945 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
946 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
949 printf("SVP[P]\tprev\n");
951 return die_("iterator ended early\n");
952 our_current_position--;
954 printf("SV[P]P\tprev\n");
956 return die_("iterator ended early\n");
957 our_current_position--;
959 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
960 padding->set_length(30);
961 if(!iterator.insert_block_after(padding, false))
962 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
963 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
966 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
969 printf("SV[P]PP\tprev\n");
971 return die_("iterator ended early\n");
972 our_current_position--;
974 printf("S[V]PPP\tprev\n");
976 return die_("iterator ended early\n");
977 our_current_position--;
979 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
980 if(iterator.delete_block(false))
981 return die_ss_("iterator.delete_block(false) should have returned false", iterator);
983 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
986 printf("[S]VPPP\tnext\n");
988 return die_("iterator ended early\n");
989 our_current_position++;
991 printf("S[V]PPP\tnext\n");
993 return die_("iterator ended early\n");
994 our_current_position++;
996 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
997 if(!iterator.delete_block(true))
998 return die_ss_("iterator.delete_block(true)", iterator);
999 our_current_position--;
1001 printf("S[V]PPP\tnext\n");
1002 if(!iterator.next())
1003 return die_("iterator ended early\n");
1004 our_current_position++;
1006 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
1007 if(!iterator.delete_block(false))
1008 return die_ss_("iterator.delete_block(false)", iterator);
1009 delete_from_our_metadata_(our_current_position--);
1011 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1014 printf("S[V]PP\tnext\n");
1015 if(!iterator.next())
1016 return die_("iterator ended early\n");
1017 our_current_position++;
1019 printf("SV[P]P\tnext\n");
1020 if(!iterator.next())
1021 return die_("iterator ended early\n");
1022 our_current_position++;
1024 printf("SVP[P]\tdelete (last block), replace with padding\n");
1025 if(!iterator.delete_block(true))
1026 return die_ss_("iterator.delete_block(false)", iterator);
1027 our_current_position--;
1029 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1032 printf("SV[P]P\tnext\n");
1033 if(!iterator.next())
1034 return die_("iterator ended early\n");
1035 our_current_position++;
1037 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1038 if(!iterator.delete_block(false))
1039 return die_ss_("iterator.delete_block(false)", iterator);
1040 delete_from_our_metadata_(our_current_position--);
1042 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1045 printf("SV[P]\tprev\n");
1046 if(!iterator.prev())
1047 return die_("iterator ended early\n");
1048 our_current_position--;
1050 printf("S[V]P\tprev\n");
1051 if(!iterator.prev())
1052 return die_("iterator ended early\n");
1053 our_current_position--;
1055 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1056 FLAC__ASSERT(our_current_position == 0);
1057 block = iterator.get_block();
1058 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
1059 FLAC__ASSERT(0 != streaminfo);
1060 streaminfo->set_sample_rate(32000);
1061 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1062 return die_("copying object");
1063 if(!iterator.set_block(block, false))
1064 return die_ss_("iterator.set_block(block, false)", iterator);
1067 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1070 printf("[S]VP\tnext\n");
1071 if(!iterator.next())
1072 return die_("iterator ended early\n");
1073 our_current_position++;
1075 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1076 app->set_id((const unsigned char *)"euh"); /* twiddle the id so that our comparison doesn't miss transposition */
1077 if(!iterator.insert_block_after(app, true))
1078 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1079 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1081 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
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]\tset APPLICATION, expand into padding of exceeding size\n");
1092 app->set_id((const unsigned char *)"fuh"); /* twiddle the id */
1093 if(!iterator.set_block(app, true))
1094 return die_ss_("iterator.set_block(app, true)", iterator);
1095 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1097 add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
1099 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1102 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1103 app->set_id((const unsigned char *)"guh"); /* twiddle the id */
1104 if(!app->set_data(data, sizeof(data), true))
1105 return die_("setting APPLICATION data");
1106 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1107 return die_("copying object");
1108 if(!iterator.set_block(app, false))
1109 return die_ss_("iterator.set_block(app, false)", iterator);
1111 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1114 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1115 app->set_id((const unsigned char *)"huh"); /* twiddle the id */
1116 if(!app->set_data(data, 12, 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 if(!iterator.set_block(app, false))
1121 return die_ss_("iterator.set_block(app, false)", iterator);
1123 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1126 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1127 app->set_id((const unsigned char *)"iuh"); /* twiddle the id */
1128 if(!app->set_data(data, sizeof(data), 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 add_to_padding_length_(our_current_position+1, -((int)sizeof(data) - 12));
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("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1140 app->set_id((const unsigned char *)"juh"); /* twiddle the id */
1141 if(!app->set_data(data, 23, true))
1142 return die_("setting APPLICATION data");
1143 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1144 return die_("copying object");
1145 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1146 return die_("copying object");
1147 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH);
1148 if(!iterator.set_block(app, true))
1149 return die_ss_("iterator.set_block(app, true)", iterator);
1151 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1154 printf("SVA[A]PP\tnext\n");
1155 if(!iterator.next())
1156 return die_("iterator ended early\n");
1157 our_current_position++;
1159 printf("SVAA[P]P\tnext\n");
1160 if(!iterator.next())
1161 return die_("iterator ended early\n");
1162 our_current_position++;
1164 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1165 padding->set_length(5);
1166 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1167 return die_("copying object");
1168 if(!iterator.set_block(padding, false))
1169 return die_ss_("iterator.set_block(padding, false)", iterator);
1171 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1174 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1175 app->set_id((const unsigned char *)"kuh"); /* twiddle the id */
1176 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1177 return die_("copying object");
1178 if(!iterator.set_block(app, false))
1179 return die_ss_("iterator.set_block(app, false)", iterator);
1181 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1184 printf("SVAAP[A]\tset PADDING (equal)\n");
1185 padding->set_length(27);
1186 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1187 return die_("copying object");
1188 if(!iterator.set_block(padding, false))
1189 return die_ss_("iterator.set_block(padding, false)", iterator);
1191 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1194 printf("SVAAP[P]\tprev\n");
1195 if(!iterator.prev())
1196 return die_("iterator ended early\n");
1197 our_current_position--;
1199 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1200 if(!iterator.delete_block(false))
1201 return die_ss_("iterator.delete_block(false)", iterator);
1202 delete_from_our_metadata_(our_current_position--);
1204 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1207 printf("SVA[A]P\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("SV[A]P\tnext\n");
1216 if(!iterator.next())
1217 return die_("iterator ended early\n");
1218 our_current_position++;
1220 printf("SVA[P]\tinsert PADDING after\n");
1221 padding->set_length(5);
1222 if(!iterator.insert_block_after(padding, false))
1223 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1224 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1227 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1230 printf("SVAP[P]\tprev\n");
1231 if(!iterator.prev())
1232 return die_("iterator ended early\n");
1233 our_current_position--;
1235 printf("SVA[P]P\tprev\n");
1236 if(!iterator.prev())
1237 return die_("iterator ended early\n");
1238 our_current_position--;
1240 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1241 if(!app->set_data(data, 32, true))
1242 return die_("setting APPLICATION data");
1243 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1244 return die_("copying object");
1245 if(!iterator.set_block(app, true))
1246 return die_ss_("iterator.set_block(app, true)", iterator);
1248 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1251 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1252 if(!app->set_data(data, 60, true))
1253 return die_("setting APPLICATION data");
1254 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1255 return die_("copying object");
1256 if(!iterator.set_block(app, true))
1257 return die_ss_("iterator.set_block(app, true)", iterator);
1259 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1262 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1263 if(!app->set_data(data, 87, true))
1264 return die_("setting APPLICATION data");
1265 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1266 return die_("copying object");
1267 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1268 if(!iterator.set_block(app, true))
1269 return die_ss_("iterator.set_block(app, true)", iterator);
1271 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1274 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1275 if(!app->set_data(data, 91, true))
1276 return die_("setting APPLICATION data");
1277 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1278 return die_("copying object");
1279 delete_from_our_metadata_(our_current_position+1);
1280 if(!iterator.set_block(app, true))
1281 return die_ss_("iterator.set_block(app, true)", iterator);
1283 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1286 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1287 if(!app->set_data(data, 100, true))
1288 return die_("setting APPLICATION data");
1289 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1290 return die_("copying object");
1291 delete_from_our_metadata_(our_current_position+1);
1292 our_metadata_.blocks[our_current_position]->set_is_last(true);
1293 if(!iterator.set_block(app, true))
1294 return die_ss_("iterator.set_block(app, true)", iterator);
1296 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1299 printf("SV[A]\tset PADDING (equal size)\n");
1300 padding->set_length(app->get_length());
1301 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1302 return die_("copying object");
1303 if(!iterator.set_block(padding, true))
1304 return die_ss_("iterator.set_block(padding, true)", iterator);
1306 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1309 printf("SV[P]\tinsert PADDING after\n");
1310 if(!iterator.insert_block_after(padding, false))
1311 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1312 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1315 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1318 printf("SVP[P]\tinsert PADDING after\n");
1319 padding->set_length(5);
1320 if(!iterator.insert_block_after(padding, false))
1321 return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1322 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1325 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1328 printf("SVPP[P]\tprev\n");
1329 if(!iterator.prev())
1330 return die_("iterator ended early\n");
1331 our_current_position--;
1333 printf("SVP[P]P\tprev\n");
1334 if(!iterator.prev())
1335 return die_("iterator ended early\n");
1336 our_current_position--;
1338 printf("SV[P]PP\tprev\n");
1339 if(!iterator.prev())
1340 return die_("iterator ended early\n");
1341 our_current_position--;
1343 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1344 if(!app->set_data(data, 101, true))
1345 return die_("setting APPLICATION data");
1346 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1347 return die_("copying object");
1348 if(!iterator.insert_block_after(app, true))
1349 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1351 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1354 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1355 if(!iterator.delete_block(false))
1356 return die_ss_("iterator.delete_block(false)", iterator);
1357 delete_from_our_metadata_(our_current_position--);
1359 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1362 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1363 if(!app->set_data(data, 97, true))
1364 return die_("setting APPLICATION data");
1365 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1366 return die_("copying object");
1367 if(!iterator.insert_block_after(app, true))
1368 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1370 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1373 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1374 if(!iterator.delete_block(false))
1375 return die_ss_("iterator.delete_block(false)", iterator);
1376 delete_from_our_metadata_(our_current_position--);
1378 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1381 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1382 if(!app->set_data(data, 100, true))
1383 return die_("setting APPLICATION data");
1384 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1385 return die_("copying object");
1386 delete_from_our_metadata_(our_current_position+1);
1387 if(!iterator.insert_block_after(app, true))
1388 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1390 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1393 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1394 if(!iterator.delete_block(false))
1395 return die_ss_("iterator.delete_block(false)", iterator);
1396 delete_from_our_metadata_(our_current_position--);
1398 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1401 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1402 if(!app->set_data(data, 96, true))
1403 return die_("setting APPLICATION data");
1404 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1405 return die_("copying object");
1406 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1407 if(!iterator.insert_block_after(app, true))
1408 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1410 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1413 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1414 if(!iterator.delete_block(false))
1415 return die_ss_("iterator.delete_block(false)", iterator);
1416 delete_from_our_metadata_(our_current_position--);
1418 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1421 printf("S[V]PP\tnext\n");
1422 if(!iterator.next())
1423 return die_("iterator ended early\n");
1424 our_current_position++;
1426 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1427 if(!iterator.delete_block(false))
1428 return die_ss_("iterator.delete_block(false)", iterator);
1429 delete_from_our_metadata_(our_current_position--);
1431 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1434 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1435 if(!app->set_data(data, 1, true))
1436 return die_("setting APPLICATION data");
1437 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1438 return die_("copying object");
1439 delete_from_our_metadata_(our_current_position+1);
1440 if(!iterator.insert_block_after(app, true))
1441 return die_ss_("iterator.insert_block_after(app, true)", iterator);
1443 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1450 if(!remove_file_(flacfile_))
1456 static bool test_level_2_(bool filename_based)
1458 FLAC::Metadata::Prototype *block;
1459 FLAC::Metadata::StreamInfo *streaminfo;
1460 FLAC::Metadata::Application *app;
1461 FLAC::Metadata::Padding *padding;
1462 FLAC__byte data[2000];
1463 unsigned our_current_position;
1465 // initialize 'data' to avoid Valgrind errors
1466 memset(data, 0, sizeof(data));
1468 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1470 printf("generate read-only file\n");
1472 if(!generate_file_(/*include_extras=*/false))
1475 if(!change_stats_(flacfile_, /*read_only=*/true))
1478 printf("create chain\n");
1479 FLAC::Metadata::Chain chain;
1480 if(!chain.is_valid())
1481 return die_("allocating memory for chain");
1483 printf("read chain\n");
1485 if(!read_chain_(chain, flacfile_, filename_based))
1486 return die_c_("reading chain", chain.status());
1488 printf("[S]VP\ttest initial metadata\n");
1490 if(!compare_chain_(chain, 0, 0))
1492 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1495 printf("switch file to read-write\n");
1497 if(!change_stats_(flacfile_, /*read-only=*/false))
1500 printf("create iterator\n");
1502 FLAC::Metadata::Iterator iterator;
1503 if(!iterator.is_valid())
1504 return die_("allocating memory for iterator");
1506 our_current_position = 0;
1508 iterator.init(chain);
1510 if(0 == (block = iterator.get_block()))
1511 return die_("getting block from iterator");
1513 FLAC__ASSERT(block->get_type() == FLAC__METADATA_TYPE_STREAMINFO);
1515 printf("[S]VP\tmodify STREAMINFO, write\n");
1517 streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
1518 FLAC__ASSERT(0 != streaminfo);
1519 streaminfo->set_sample_rate(32000);
1520 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1521 return die_("copying object");
1524 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1525 return die_c_("during chain.write(false, true)", chain.status());
1526 block = iterator.get_block();
1527 if(!compare_chain_(chain, our_current_position, block))
1530 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1533 printf("[S]VP\tnext\n");
1534 if(!iterator.next())
1535 return die_("iterator ended early\n");
1536 our_current_position++;
1538 printf("S[V]P\tnext\n");
1539 if(!iterator.next())
1540 return die_("iterator ended early\n");
1541 our_current_position++;
1543 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1544 if(0 == (block = iterator.get_block()))
1545 return die_("getting block from iterator");
1546 if(0 == (app = new FLAC::Metadata::Application()))
1547 return die_("new FLAC::Metadata::Application()");
1548 app->set_id((const unsigned char *)"duh");
1549 if(!app->set_data(data, block->get_length()-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1550 return die_("setting APPLICATION data");
1552 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1553 return die_("copying object");
1554 if(!iterator.set_block(app))
1555 return die_c_("iterator.set_block(app)", chain.status());
1557 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1558 return die_c_("during chain.write(false, false)", chain.status());
1559 block = iterator.get_block();
1560 if(!compare_chain_(chain, our_current_position, block))
1563 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1566 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1567 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1568 return die_("copying object");
1569 if(!app->set_data(data, 26, true))
1570 return die_("setting APPLICATION data");
1571 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1572 return die_("copying object");
1573 if(!iterator.set_block(app))
1574 return die_c_("iterator.set_block(app)", chain.status());
1576 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1577 return die_c_("during chain.write(false, false)", chain.status());
1578 block = iterator.get_block();
1579 if(!compare_chain_(chain, our_current_position, block))
1582 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1585 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1586 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1587 return die_("copying object");
1588 if(!app->set_data(data, 28, true))
1589 return die_("setting APPLICATION data");
1590 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1591 return die_("copying object");
1592 if(!iterator.set_block(app))
1593 return die_c_("iterator.set_block(app)", chain.status());
1595 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1596 return die_c_("during chain.write(false, false)", chain.status());
1597 block = iterator.get_block();
1598 if(!compare_chain_(chain, our_current_position, block))
1601 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1604 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1605 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1606 return die_("copying object");
1607 if(!app->set_data(data, 36, true))
1608 return die_("setting APPLICATION data");
1609 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1610 return die_("copying object");
1611 if(!iterator.set_block(app))
1612 return die_c_("iterator.set_block(app)", chain.status());
1614 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1615 return die_c_("during chain.write(false, false)", chain.status());
1616 block = iterator.get_block();
1617 if(!compare_chain_(chain, our_current_position, block))
1620 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1623 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1624 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1625 return die_("copying object");
1626 if(!app->set_data(data, 33, true))
1627 return die_("setting APPLICATION data");
1628 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1629 return die_("copying object");
1630 if(!iterator.set_block(app))
1631 return die_c_("iterator.set_block(app)", chain.status());
1633 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1634 return die_c_("during chain.write(true, false)", chain.status());
1635 block = iterator.get_block();
1636 if(!compare_chain_(chain, our_current_position, block))
1639 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1642 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1643 if(0 == (padding = new FLAC::Metadata::Padding()))
1644 return die_("creating PADDING block");
1645 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1646 return die_("copying object");
1647 if(!app->set_data(data, 29, true))
1648 return die_("setting APPLICATION data");
1649 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1650 return die_("copying object");
1651 padding->set_length(0);
1652 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1653 return die_("internal error");
1654 if(!iterator.set_block(app))
1655 return die_c_("iterator.set_block(app)", chain.status());
1657 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1658 return die_c_("during chain.write(true, false)", chain.status());
1659 block = iterator.get_block();
1660 if(!compare_chain_(chain, our_current_position, block))
1663 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1666 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1667 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1668 return die_("copying object");
1669 if(!app->set_data(data, 16, true))
1670 return die_("setting APPLICATION data");
1671 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1672 return die_("copying object");
1673 dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(13);
1674 if(!iterator.set_block(app))
1675 return die_c_("iterator.set_block(app)", chain.status());
1677 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1678 return die_c_("during chain.write(true, false)", chain.status());
1679 block = iterator.get_block();
1680 if(!compare_chain_(chain, our_current_position, block))
1683 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1686 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1687 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1688 return die_("copying object");
1689 if(!app->set_data(data, 50, true))
1690 return die_("setting APPLICATION data");
1691 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1692 return die_("copying object");
1693 if(!iterator.set_block(app))
1694 return die_c_("iterator.set_block(app)", chain.status());
1696 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1697 return die_c_("during chain.write(true, false)", chain.status());
1698 block = iterator.get_block();
1699 if(!compare_chain_(chain, our_current_position, block))
1702 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1705 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1706 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1707 return die_("copying object");
1708 if(!app->set_data(data, 56, true))
1709 return die_("setting APPLICATION data");
1710 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1711 return die_("copying object");
1712 add_to_padding_length_(our_current_position+1, -(56 - 50));
1713 if(!iterator.set_block(app))
1714 return die_c_("iterator.set_block(app)", chain.status());
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 block = iterator.get_block();
1719 if(!compare_chain_(chain, our_current_position, block))
1722 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1725 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1726 if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1727 return die_("copying object");
1728 if(!app->set_data(data, 67, true))
1729 return die_("setting APPLICATION data");
1730 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1731 return die_("copying object");
1732 delete_from_our_metadata_(our_current_position+1);
1733 if(!iterator.set_block(app))
1734 return die_c_("iterator.set_block(app)", chain.status());
1736 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1737 return die_c_("during chain.write(true, false)", chain.status());
1738 block = iterator.get_block();
1739 if(!compare_chain_(chain, our_current_position, block))
1742 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1745 printf("SV[A]\tprev\n");
1746 if(!iterator.prev())
1747 return die_("iterator ended early\n");
1748 our_current_position--;
1750 printf("S[V]A\tprev\n");
1751 if(!iterator.prev())
1752 return die_("iterator ended early\n");
1753 our_current_position--;
1755 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1756 if(0 == (padding = new FLAC::Metadata::Padding()))
1757 return die_("creating PADDING block");
1758 padding->set_length(30);
1759 if(!iterator.insert_block_before(padding))
1760 printf("\titerator.insert_block_before() returned false like it should\n");
1762 return die_("iterator.insert_block_before() should have returned false");
1764 printf("[S]VA\tnext\n");
1765 if(!iterator.next())
1766 return die_("iterator ended early\n");
1767 our_current_position++;
1769 printf("S[V]A\tinsert PADDING after\n");
1770 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1771 return die_("copying metadata");
1772 if(!iterator.insert_block_after(padding))
1773 return die_("iterator.insert_block_after(padding)");
1775 block = iterator.get_block();
1776 if(!compare_chain_(chain, our_current_position, block))
1780 printf("SV[P]A\tinsert PADDING before\n");
1781 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1782 return die_("creating PADDING block");
1783 padding->set_length(17);
1784 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1785 return die_("copying metadata");
1786 if(!iterator.insert_block_before(padding))
1787 return die_("iterator.insert_block_before(padding)");
1789 block = iterator.get_block();
1790 if(!compare_chain_(chain, our_current_position, block))
1794 printf("SV[P]PA\tinsert PADDING before\n");
1795 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1796 return die_("creating PADDING block");
1797 padding->set_length(0);
1798 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1799 return die_("copying metadata");
1800 if(!iterator.insert_block_before(padding))
1801 return die_("iterator.insert_block_before(padding)");
1803 block = iterator.get_block();
1804 if(!compare_chain_(chain, our_current_position, block))
1808 printf("SV[P]PPA\tnext\n");
1809 if(!iterator.next())
1810 return die_("iterator ended early\n");
1811 our_current_position++;
1813 printf("SVP[P]PA\tnext\n");
1814 if(!iterator.next())
1815 return die_("iterator ended early\n");
1816 our_current_position++;
1818 printf("SVPP[P]A\tnext\n");
1819 if(!iterator.next())
1820 return die_("iterator ended early\n");
1821 our_current_position++;
1823 printf("SVPPP[A]\tinsert PADDING after\n");
1824 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1825 return die_("creating PADDING block");
1826 padding->set_length(57);
1827 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1828 return die_("copying metadata");
1829 if(!iterator.insert_block_after(padding))
1830 return die_("iterator.insert_block_after(padding)");
1832 block = iterator.get_block();
1833 if(!compare_chain_(chain, our_current_position, block))
1837 printf("SVPPPA[P]\tinsert PADDING before\n");
1838 if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1839 return die_("creating PADDING block");
1840 padding->set_length(99);
1841 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1842 return die_("copying metadata");
1843 if(!iterator.insert_block_before(padding))
1844 return die_("iterator.insert_block_before(padding)");
1846 block = iterator.get_block();
1847 if(!compare_chain_(chain, our_current_position, block))
1852 our_current_position = 0;
1854 printf("SVPPPAPP\tmerge padding\n");
1855 chain.merge_padding();
1856 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->get_length());
1857 add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->get_length());
1858 add_to_padding_length_(6, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->get_length());
1859 delete_from_our_metadata_(7);
1860 delete_from_our_metadata_(4);
1861 delete_from_our_metadata_(3);
1863 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1864 return die_c_("during chain.write(true, false)", chain.status());
1865 if(!compare_chain_(chain, 0, 0))
1867 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1870 printf("SVPAP\tsort padding\n");
1871 chain.sort_padding();
1872 add_to_padding_length_(4, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->get_length());
1873 delete_from_our_metadata_(2);
1875 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1876 return die_c_("during chain.write(true, false)", chain.status());
1877 if(!compare_chain_(chain, 0, 0))
1879 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1882 printf("create iterator\n");
1884 FLAC::Metadata::Iterator iterator;
1885 if(!iterator.is_valid())
1886 return die_("allocating memory for iterator");
1888 our_current_position = 0;
1890 iterator.init(chain);
1892 printf("[S]VAP\tnext\n");
1893 if(!iterator.next())
1894 return die_("iterator ended early\n");
1895 our_current_position++;
1897 printf("S[V]AP\tnext\n");
1898 if(!iterator.next())
1899 return die_("iterator ended early\n");
1900 our_current_position++;
1902 printf("SV[A]P\tdelete middle block, replace with padding\n");
1903 if(0 == (padding = new FLAC::Metadata::Padding()))
1904 return die_("creating PADDING block");
1905 padding->set_length(71);
1906 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1907 return die_("copying object");
1908 if(!iterator.delete_block(/*replace_with_padding=*/true))
1909 return die_c_("iterator.delete_block(true)", chain.status());
1911 block = iterator.get_block();
1912 if(!compare_chain_(chain, our_current_position, block))
1916 printf("S[V]PP\tnext\n");
1917 if(!iterator.next())
1918 return die_("iterator ended early\n");
1919 our_current_position++;
1921 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1922 delete_from_our_metadata_(our_current_position--);
1923 if(!iterator.delete_block(/*replace_with_padding=*/false))
1924 return die_c_("iterator.delete_block(false)", chain.status());
1926 block = iterator.get_block();
1927 if(!compare_chain_(chain, our_current_position, block))
1931 printf("S[V]P\tnext\n");
1932 if(!iterator.next())
1933 return die_("iterator ended early\n");
1934 our_current_position++;
1936 printf("SV[P]\tdelete last block, replace with padding\n");
1937 if(0 == (padding = new FLAC::Metadata::Padding()))
1938 return die_("creating PADDING block");
1939 padding->set_length(219);
1940 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1941 return die_("copying object");
1942 if(!iterator.delete_block(/*replace_with_padding=*/true))
1943 return die_c_("iterator.delete_block(true)", chain.status());
1945 block = iterator.get_block();
1946 if(!compare_chain_(chain, our_current_position, block))
1950 printf("S[V]P\tnext\n");
1951 if(!iterator.next())
1952 return die_("iterator ended early\n");
1953 our_current_position++;
1955 printf("SV[P]\tdelete last block, don't replace with padding\n");
1956 delete_from_our_metadata_(our_current_position--);
1957 if(!iterator.delete_block(/*replace_with_padding=*/false))
1958 return die_c_("iterator.delete_block(false)", chain.status());
1960 block = iterator.get_block();
1961 if(!compare_chain_(chain, our_current_position, block))
1965 printf("S[V]\tprev\n");
1966 if(!iterator.prev())
1967 return die_("iterator ended early\n");
1968 our_current_position--;
1970 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1971 if(iterator.delete_block(/*replace_with_padding=*/false))
1972 return die_("iterator.delete_block() on STREAMINFO should have failed but didn't");
1974 block = iterator.get_block();
1975 if(!compare_chain_(chain, our_current_position, block))
1979 } // delete iterator
1980 our_current_position = 0;
1982 printf("SV\tmerge padding\n");
1983 chain.merge_padding();
1985 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1986 return die_c_("during chain.write(false, false)", chain.status());
1987 if(!compare_chain_(chain, 0, 0))
1989 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
1992 printf("SV\tsort padding\n");
1993 chain.sort_padding();
1995 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1996 return die_c_("during chain.write(false, false)", chain.status());
1997 if(!compare_chain_(chain, 0, 0))
1999 if(!test_file_(flacfile_, /*ignore_metadata=*/false))
2002 if(!remove_file_(flacfile_))
2008 static bool test_level_2_misc_()
2010 ::FLAC__IOCallbacks callbacks;
2012 memset(&callbacks, 0, sizeof(callbacks));
2013 callbacks.read = (::FLAC__IOCallback_Read)fread;
2014 #ifdef FLAC__VALGRIND_TESTING
2015 callbacks.write = chain_write_cb_;
2017 callbacks.write = (::FLAC__IOCallback_Write)fwrite;
2019 callbacks.seek = chain_seek_cb_;
2020 callbacks.tell = chain_tell_cb_;
2021 callbacks.eof = chain_eof_cb_;
2023 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
2025 printf("generate file\n");
2027 if(!generate_file_(/*include_extras=*/false))
2030 printf("create chain\n");
2031 FLAC::Metadata::Chain chain;
2032 if(!chain.is_valid())
2033 return die_("allocating chain");
2035 printf("read chain (filename-based)\n");
2037 if(!chain.read(flacfile_))
2038 return die_c_("reading chain", chain.status());
2040 printf("write chain with wrong method Chain::write(with callbacks)\n");
2042 if(chain.write(/*use_padding=*/false, 0, callbacks))
2043 return die_c_("mismatched write should have failed", chain.status());
2044 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2045 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
2046 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2049 printf("read chain (filename-based)\n");
2051 if(!chain.read(flacfile_))
2052 return die_c_("reading chain", chain.status());
2054 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
2056 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
2057 return die_c_("mismatched write should have failed", chain.status());
2058 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2059 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
2060 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2063 printf("read chain (callback-based)\n");
2065 FILE *file = fopen(flacfile_, "rb");
2067 return die_("opening file");
2068 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
2070 return die_c_("reading chain", chain.status());
2075 printf("write chain with wrong method write()\n");
2077 if(chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false))
2078 return die_c_("mismatched write should have failed", chain.status());
2079 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2080 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
2081 printf(" OK: write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2084 printf("read chain (callback-based)\n");
2086 FILE *file = fopen(flacfile_, "rb");
2088 return die_("opening file");
2089 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
2091 return die_c_("reading chain", chain.status());
2096 printf("testing Chain::check_if_tempfile_needed()... ");
2098 if(!chain.check_if_tempfile_needed(/*use_padding=*/false))
2099 printf("OK: Chain::check_if_tempfile_needed() returned false like it should\n");
2101 return die_("Chain::check_if_tempfile_needed() returned true but shouldn't have");
2103 printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
2105 if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
2106 return die_c_("mismatched write should have failed", chain.status());
2107 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2108 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
2109 printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2112 printf("read chain (callback-based)\n");
2114 FILE *file = fopen(flacfile_, "rb");
2116 return die_("opening file");
2117 if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
2119 return die_c_("reading chain", chain.status());
2124 printf("create iterator\n");
2126 FLAC::Metadata::Iterator iterator;
2127 if(!iterator.is_valid())
2128 return die_("allocating memory for iterator");
2130 iterator.init(chain);
2132 printf("[S]VP\tnext\n");
2133 if(!iterator.next())
2134 return die_("iterator ended early\n");
2136 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2137 if(!iterator.delete_block(/*replace_with_padding=*/false))
2138 return die_c_("block delete failed\n", chain.status());
2140 printf("testing Chain::check_if_tempfile_needed()... ");
2142 if(chain.check_if_tempfile_needed(/*use_padding=*/false))
2143 printf("OK: Chain::check_if_tempfile_needed() returned true like it should\n");
2145 return die_("Chain::check_if_tempfile_needed() returned false but shouldn't have");
2147 printf("write chain with wrong method Chain::write(with callbacks)\n");
2149 if(chain.write(/*use_padding=*/false, 0, callbacks))
2150 return die_c_("mismatched write should have failed", chain.status());
2151 if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2152 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
2153 printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2156 } // delete iterator
2158 if(!remove_file_(flacfile_))
2164 bool test_metadata_file_manipulation()
2166 printf("\n+++ libFLAC++ unit test: metadata manipulation\n\n");
2168 our_metadata_.num_blocks = 0;
2170 if(!test_level_0_())
2173 if(!test_level_1_())
2176 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2178 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2180 if(!test_level_2_misc_())