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.
24 #include <stdlib.h> /* for malloc() */
25 #if defined _MSC_VER || defined __MINGW32__
26 #include <sys/utime.h> /* for utime() */
27 #include <io.h> /* for chmod() */
28 //@@@ [2G limit] hacks for MSVC6
32 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
33 #include <utime.h> /* for utime() */
34 #include <unistd.h> /* for chown(), unlink() */
36 #include <sys/stat.h> /* for stat(), maybe chmod() */
37 #include "FLAC/assert.h"
38 #include "FLAC/stream_decoder.h"
39 #include "FLAC/metadata.h"
40 #include "share/grabbag.h"
41 #include "test_libs_common/file_utils_flac.h"
42 #include "test_libs_common/metadata_utils.h"
45 /******************************************************************************
46 The general strategy of these tests (for interface levels 1 and 2) is
47 to create a dummy FLAC file with a known set of initial metadata
48 blocks, then keep a mirror locally of what we expect the metadata to be
49 after each operation. Then testing becomes a simple matter of running
50 a FLAC__StreamDecoder over the dummy file after each operation, comparing
51 the decoded metadata to what's in our local copy. If there are any
52 differences in the metadata, or the actual audio data is corrupted, we
53 will catch it while decoding.
54 ******************************************************************************/
57 FLAC__bool error_occurred;
58 } decoder_client_struct;
61 FLAC__StreamMetadata *blocks[64];
63 } our_metadata_struct;
65 static const char *flacfile_ = "metadata.flac";
67 /* our copy of the metadata in flacfile_ */
68 static our_metadata_struct our_metadata_;
70 /* the current block number that corresponds to the position of the iterator we are testing */
71 static unsigned mc_our_block_number_ = 0;
73 static FLAC__bool die_(const char *msg)
75 printf("ERROR: %s\n", msg);
79 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
81 printf("ERROR: %s\n", msg);
82 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
86 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
88 printf("ERROR: %s\n", msg);
89 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
93 static void *malloc_or_die_(size_t size)
95 void *x = malloc(size);
97 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
103 static char *strdup_or_die_(const char *s)
107 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
113 /* functions for working with our metadata copy */
115 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
118 FLAC__StreamMetadata *obj = block;
119 FLAC__ASSERT(position < our_metadata_.num_blocks);
121 if(0 == (obj = FLAC__metadata_object_clone(block)))
122 return die_("during FLAC__metadata_object_clone()");
124 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
125 our_metadata_.blocks[position] = obj;
127 /* set the is_last flags */
128 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
129 our_metadata_.blocks[i]->is_last = false;
130 our_metadata_.blocks[i]->is_last = true;
135 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
138 FLAC__StreamMetadata *obj = block;
140 if(0 == (obj = FLAC__metadata_object_clone(block)))
141 return die_("during FLAC__metadata_object_clone()");
143 if(position > our_metadata_.num_blocks) {
144 position = our_metadata_.num_blocks;
147 for(i = our_metadata_.num_blocks; i > position; i--)
148 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
150 our_metadata_.blocks[position] = obj;
151 our_metadata_.num_blocks++;
153 /* set the is_last flags */
154 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
155 our_metadata_.blocks[i]->is_last = false;
156 our_metadata_.blocks[i]->is_last = true;
161 static void delete_from_our_metadata_(unsigned position)
164 FLAC__ASSERT(position < our_metadata_.num_blocks);
165 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
166 for(i = position; i < our_metadata_.num_blocks - 1; i++)
167 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
168 our_metadata_.num_blocks--;
170 /* set the is_last flags */
171 if(our_metadata_.num_blocks > 0) {
172 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
173 our_metadata_.blocks[i]->is_last = false;
174 our_metadata_.blocks[i]->is_last = true;
179 * This wad of functions supports filename- and callback-based chain reading/writing.
180 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
182 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
184 static const char *tempfile_suffix = ".metadata_edit";
186 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
188 strcpy(*tempfilename, filename);
189 strcat(*tempfilename, tempfile_suffix);
191 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
197 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
200 (void)fclose(*tempfile);
204 if(0 != *tempfilename) {
205 (void)unlink(*tempfilename);
211 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
213 FLAC__ASSERT(0 != filename);
214 FLAC__ASSERT(0 != tempfile);
215 FLAC__ASSERT(0 != tempfilename);
216 FLAC__ASSERT(0 != *tempfilename);
219 (void)fclose(*tempfile);
223 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
224 /* on some flavors of windows, rename() will fail if the destination already exists */
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 FLAC__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__ && !defined __EMX__
260 (void)chown(filename, stats->st_uid, -1);
261 (void)chown(filename, -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 off_t o = (off_t)offset;
279 FLAC__ASSERT(offset == o);
280 return fseeko((FILE*)handle, o, whence);
283 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
285 return ftello((FILE*)handle);
288 static int chain_eof_cb_(FLAC__IOHandle handle)
290 return feof((FILE*)handle);
293 static FLAC__bool write_chain_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats, FLAC__bool filename_based, const char *filename)
296 return FLAC__metadata_chain_write(chain, 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(FLAC__metadata_chain_check_if_tempfile_needed(chain, 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(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, 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(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
351 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
354 return FLAC__metadata_chain_read(chain, flacfile_);
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 = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
375 /* function for comparing our metadata to a FLAC__Metadata_Chain */
377 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
380 FLAC__Metadata_Iterator *iterator;
381 FLAC__StreamMetadata *block;
382 FLAC__bool next_ok = true;
384 FLAC__ASSERT(0 != chain);
386 printf("\tcomparing chain... ");
389 if(0 == (iterator = FLAC__metadata_iterator_new()))
390 return die_("allocating memory for iterator");
392 FLAC__metadata_iterator_init(iterator, chain);
399 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
400 FLAC__metadata_iterator_delete(iterator);
401 return die_("getting block from iterator");
404 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
405 FLAC__metadata_iterator_delete(iterator);
406 return die_("metadata block mismatch");
410 next_ok = FLAC__metadata_iterator_next(iterator);
411 } while(i < our_metadata_.num_blocks && next_ok);
413 FLAC__metadata_iterator_delete(iterator);
416 return die_("chain has more blocks than expected");
418 if(i < our_metadata_.num_blocks)
419 return die_("short block count in chain");
421 if(0 != current_block) {
422 printf("CURRENT_POSITION... ");
425 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
426 return die_("metadata block mismatch");
434 /* decoder callbacks for checking the file */
436 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
438 (void)decoder, (void)buffer, (void)client_data;
441 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
442 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
444 printf("content... ");
448 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
451 /* this version pays no attention to the metadata */
452 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
454 (void)decoder, (void)metadata, (void)client_data;
456 printf("%d... ", mc_our_block_number_);
459 mc_our_block_number_++;
462 /* this version is used when we want to compare to our metadata copy */
463 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
465 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
469 /* don't bother checking if we've already hit an error */
470 if(dcd->error_occurred)
473 printf("%d... ", mc_our_block_number_);
476 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
477 (void)die_("got more metadata blocks than expected");
478 dcd->error_occurred = true;
481 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
482 (void)die_("metadata block mismatch");
483 dcd->error_occurred = true;
486 mc_our_block_number_++;
489 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
491 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
494 dcd->error_occurred = true;
495 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
498 static FLAC__bool generate_file_(FLAC__bool include_extras)
500 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
501 FLAC__StreamMetadata *metadata[4];
502 unsigned i = 0, n = 0;
504 printf("generating FLAC file for test\n");
506 while(our_metadata_.num_blocks > 0)
507 delete_from_our_metadata_(0);
509 streaminfo.is_last = false;
510 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
511 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
512 streaminfo.data.stream_info.min_blocksize = 576;
513 streaminfo.data.stream_info.max_blocksize = 576;
514 streaminfo.data.stream_info.min_framesize = 0;
515 streaminfo.data.stream_info.max_framesize = 0;
516 streaminfo.data.stream_info.sample_rate = 44100;
517 streaminfo.data.stream_info.channels = 1;
518 streaminfo.data.stream_info.bits_per_sample = 8;
519 streaminfo.data.stream_info.total_samples = 0;
520 memset(streaminfo.data.stream_info.md5sum, 0, 16);
523 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
524 vorbiscomment.is_last = false;
525 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
526 vorbiscomment.length = (4 + vendor_string_length) + 4;
527 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
528 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
529 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
530 vorbiscomment.data.vorbis_comment.num_comments = 0;
531 vorbiscomment.data.vorbis_comment.comments = 0;
535 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
536 return die_("priming our metadata");
537 cuesheet->is_last = false;
538 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
539 cuesheet->data.cue_sheet.lead_in = 123;
540 cuesheet->data.cue_sheet.is_cd = false;
541 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
542 return die_("priming our metadata");
543 cuesheet->data.cue_sheet.tracks[0].number = 1;
544 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
545 return die_("priming our metadata");
549 picture.is_last = false;
550 picture.type = FLAC__METADATA_TYPE_PICTURE;
553 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
554 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
555 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
556 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
557 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
558 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
559 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
562 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
563 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
564 picture.length += strlen(picture.data.picture.mime_type);
565 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
566 picture.length += strlen((const char *)picture.data.picture.description);
567 picture.data.picture.width = 300;
568 picture.data.picture.height = 300;
569 picture.data.picture.depth = 24;
570 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
571 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
572 picture.length += picture.data.picture.data_length;
575 padding.is_last = true;
576 padding.type = FLAC__METADATA_TYPE_PADDING;
577 padding.length = 1234;
579 metadata[n++] = &vorbiscomment;
581 metadata[n++] = cuesheet;
582 metadata[n++] = &picture;
584 metadata[n++] = &padding;
587 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
588 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
589 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
590 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
591 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
593 return die_("priming our metadata");
595 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
596 return die_("creating the encoded file");
598 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
603 static FLAC__bool test_file_(const char *filename, FLAC__StreamDecoderMetadataCallback metadata_callback)
605 FLAC__StreamDecoder *decoder;
606 decoder_client_struct decoder_client_data;
608 FLAC__ASSERT(0 != filename);
609 FLAC__ASSERT(0 != metadata_callback);
611 mc_our_block_number_ = 0;
612 decoder_client_data.error_occurred = false;
614 printf("\ttesting '%s'... ", filename);
617 if(0 == (decoder = FLAC__stream_decoder_new()))
618 return die_("couldn't allocate decoder instance");
620 FLAC__stream_decoder_set_md5_checking(decoder, true);
621 FLAC__stream_decoder_set_metadata_respond_all(decoder);
622 if(FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
623 FLAC__stream_decoder_finish(decoder);
624 FLAC__stream_decoder_delete(decoder);
625 return die_("initializing decoder\n");
627 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
628 FLAC__stream_decoder_finish(decoder);
629 FLAC__stream_decoder_delete(decoder);
630 return die_("decoding file\n");
633 FLAC__stream_decoder_finish(decoder);
634 FLAC__stream_decoder_delete(decoder);
636 if(decoder_client_data.error_occurred)
639 if(mc_our_block_number_ != our_metadata_.num_blocks)
640 return die_("short metadata block count");
646 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
648 if(!grabbag__file_change_stats(filename, read_only))
649 return die_("during grabbag__file_change_stats()");
654 static FLAC__bool remove_file_(const char *filename)
656 while(our_metadata_.num_blocks > 0)
657 delete_from_our_metadata_(0);
659 if(!grabbag__file_remove_file(filename))
660 return die_("removing file");
665 static FLAC__bool test_level_0_()
667 FLAC__StreamMetadata streaminfo;
668 FLAC__StreamMetadata *tags = 0;
669 FLAC__StreamMetadata *cuesheet = 0;
670 FLAC__StreamMetadata *picture = 0;
672 printf("\n\n++++++ testing level 0 interface\n");
674 if(!generate_file_(/*include_extras=*/true))
677 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
680 printf("testing FLAC__metadata_get_streaminfo()... ");
682 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
683 return die_("during FLAC__metadata_get_streaminfo()");
685 /* check to see if some basic data matches (c.f. generate_file_()) */
686 if(streaminfo.data.stream_info.channels != 1)
687 return die_("mismatch in streaminfo.data.stream_info.channels");
688 if(streaminfo.data.stream_info.bits_per_sample != 8)
689 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
690 if(streaminfo.data.stream_info.sample_rate != 44100)
691 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
692 if(streaminfo.data.stream_info.min_blocksize != 576)
693 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
694 if(streaminfo.data.stream_info.max_blocksize != 576)
695 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
699 printf("testing FLAC__metadata_get_tags()... ");
701 if(!FLAC__metadata_get_tags(flacfile_, &tags))
702 return die_("during FLAC__metadata_get_tags()");
704 /* check to see if some basic data matches (c.f. generate_file_()) */
705 if(tags->data.vorbis_comment.num_comments != 0)
706 return die_("mismatch in tags->data.vorbis_comment.num_comments");
710 FLAC__metadata_object_delete(tags);
712 printf("testing FLAC__metadata_get_cuesheet()... ");
714 if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
715 return die_("during FLAC__metadata_get_cuesheet()");
717 /* check to see if some basic data matches (c.f. generate_file_()) */
718 if(cuesheet->data.cue_sheet.lead_in != 123)
719 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
723 FLAC__metadata_object_delete(cuesheet);
725 printf("testing FLAC__metadata_get_picture()... ");
727 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)))
728 return die_("during FLAC__metadata_get_picture()");
730 /* check to see if some basic data matches (c.f. generate_file_()) */
731 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
732 return die_("mismatch in picture->data.picture.type");
736 FLAC__metadata_object_delete(picture);
738 if(!remove_file_(flacfile_))
744 static FLAC__bool test_level_1_()
746 FLAC__Metadata_SimpleIterator *iterator;
747 FLAC__StreamMetadata *block, *app, *padding;
748 FLAC__byte data[1000];
749 unsigned our_current_position = 0;
751 /* initialize 'data' to avoid Valgrind errors */
752 memset(data, 0, sizeof(data));
754 printf("\n\n++++++ testing level 1 interface\n");
756 /************************************************************/
758 printf("simple iterator on read-only file\n");
760 if(!generate_file_(/*include_extras=*/false))
763 if(!change_stats_(flacfile_, /*read_only=*/true))
766 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
769 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
770 return die_("FLAC__metadata_simple_iterator_new()");
772 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
773 return die_("FLAC__metadata_simple_iterator_init() returned false");
775 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
776 if(FLAC__metadata_simple_iterator_is_writable(iterator))
777 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
779 printf("iterate forwards\n");
781 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
782 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
783 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
784 return die_("getting block 0");
785 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
786 return die_("expected STREAMINFO type");
788 return die_("expected is_last to be false");
789 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
790 return die_("bad STREAMINFO length");
791 /* check to see if some basic data matches (c.f. generate_file_()) */
792 if(block->data.stream_info.channels != 1)
793 return die_("mismatch in channels");
794 if(block->data.stream_info.bits_per_sample != 8)
795 return die_("mismatch in bits_per_sample");
796 if(block->data.stream_info.sample_rate != 44100)
797 return die_("mismatch in sample_rate");
798 if(block->data.stream_info.min_blocksize != 576)
799 return die_("mismatch in min_blocksize");
800 if(block->data.stream_info.max_blocksize != 576)
801 return die_("mismatch in max_blocksize");
802 FLAC__metadata_object_delete(block);
804 if(!FLAC__metadata_simple_iterator_next(iterator))
805 return die_("forward iterator ended early");
806 our_current_position++;
808 if(!FLAC__metadata_simple_iterator_next(iterator))
809 return die_("forward iterator ended early");
810 our_current_position++;
812 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
813 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
814 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
815 return die_("getting block 2");
816 if(block->type != FLAC__METADATA_TYPE_PADDING)
817 return die_("expected PADDING type");
819 return die_("expected is_last to be true");
820 /* check to see if some basic data matches (c.f. generate_file_()) */
821 if(block->length != 1234)
822 return die_("bad PADDING length");
823 FLAC__metadata_object_delete(block);
825 if(FLAC__metadata_simple_iterator_next(iterator))
826 return die_("forward iterator returned true but should have returned false");
828 printf("iterate backwards\n");
829 if(!FLAC__metadata_simple_iterator_prev(iterator))
830 return die_("reverse iterator ended early");
831 if(!FLAC__metadata_simple_iterator_prev(iterator))
832 return die_("reverse iterator ended early");
833 if(FLAC__metadata_simple_iterator_prev(iterator))
834 return die_("reverse iterator returned true but should have returned false");
836 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
838 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
839 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
841 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
843 FLAC__metadata_simple_iterator_delete(iterator);
845 /************************************************************/
847 printf("simple iterator on writable file\n");
849 if(!change_stats_(flacfile_, /*read-only=*/false))
852 printf("creating APPLICATION block\n");
854 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
855 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
856 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
858 printf("creating PADDING block\n");
860 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
861 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
862 padding->length = 20;
864 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
865 return die_("FLAC__metadata_simple_iterator_new()");
867 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
868 return die_("FLAC__metadata_simple_iterator_init() returned false");
869 our_current_position = 0;
871 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
873 printf("[S]VP\ttry to write over STREAMINFO block...\n");
874 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
875 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
877 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
879 printf("[S]VP\tnext\n");
880 if(!FLAC__metadata_simple_iterator_next(iterator))
881 return die_("iterator ended early\n");
882 our_current_position++;
884 printf("S[V]P\tnext\n");
885 if(!FLAC__metadata_simple_iterator_next(iterator))
886 return die_("iterator ended early\n");
887 our_current_position++;
889 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
890 padding->length = 25;
891 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
892 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
893 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
896 printf("SVP[P]\tprev\n");
897 if(!FLAC__metadata_simple_iterator_prev(iterator))
898 return die_("iterator ended early\n");
899 our_current_position--;
901 printf("SV[P]P\tprev\n");
902 if(!FLAC__metadata_simple_iterator_prev(iterator))
903 return die_("iterator ended early\n");
904 our_current_position--;
906 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
907 padding->length = 30;
908 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
909 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
910 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
913 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
916 printf("SV[P]PP\tprev\n");
917 if(!FLAC__metadata_simple_iterator_prev(iterator))
918 return die_("iterator ended early\n");
919 our_current_position--;
921 printf("S[V]PPP\tprev\n");
922 if(!FLAC__metadata_simple_iterator_prev(iterator))
923 return die_("iterator ended early\n");
924 our_current_position--;
926 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
927 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
928 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
930 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
933 printf("[S]VPPP\tnext\n");
934 if(!FLAC__metadata_simple_iterator_next(iterator))
935 return die_("iterator ended early\n");
936 our_current_position++;
938 printf("S[V]PPP\tnext\n");
939 if(!FLAC__metadata_simple_iterator_next(iterator))
940 return die_("iterator ended early\n");
941 our_current_position++;
943 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
944 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
945 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
946 our_current_position--;
948 printf("S[V]PPP\tnext\n");
949 if(!FLAC__metadata_simple_iterator_next(iterator))
950 return die_("iterator ended early\n");
951 our_current_position++;
953 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
954 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
955 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
956 delete_from_our_metadata_(our_current_position--);
958 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
961 printf("S[V]PP\tnext\n");
962 if(!FLAC__metadata_simple_iterator_next(iterator))
963 return die_("iterator ended early\n");
964 our_current_position++;
966 printf("SV[P]P\tnext\n");
967 if(!FLAC__metadata_simple_iterator_next(iterator))
968 return die_("iterator ended early\n");
969 our_current_position++;
971 printf("SVP[P]\tdelete (last block), replace with padding\n");
972 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
973 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
974 our_current_position--;
976 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
979 printf("SV[P]P\tnext\n");
980 if(!FLAC__metadata_simple_iterator_next(iterator))
981 return die_("iterator ended early\n");
982 our_current_position++;
984 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
985 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
986 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
987 delete_from_our_metadata_(our_current_position--);
989 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
992 printf("SV[P]\tprev\n");
993 if(!FLAC__metadata_simple_iterator_prev(iterator))
994 return die_("iterator ended early\n");
995 our_current_position--;
997 printf("S[V]P\tprev\n");
998 if(!FLAC__metadata_simple_iterator_prev(iterator))
999 return die_("iterator ended early\n");
1000 our_current_position--;
1002 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1003 FLAC__ASSERT(our_current_position == 0);
1004 block = FLAC__metadata_simple_iterator_get_block(iterator);
1005 block->data.stream_info.sample_rate = 32000;
1006 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1007 return die_("copying object");
1008 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1009 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1010 FLAC__metadata_object_delete(block);
1012 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1015 printf("[S]VP\tnext\n");
1016 if(!FLAC__metadata_simple_iterator_next(iterator))
1017 return die_("iterator ended early\n");
1018 our_current_position++;
1020 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1021 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1022 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1023 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1024 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1026 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1028 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1031 printf("SV[A]P\tnext\n");
1032 if(!FLAC__metadata_simple_iterator_next(iterator))
1033 return die_("iterator ended early\n");
1034 our_current_position++;
1036 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1037 app->data.application.id[0] = 'f'; /* twiddle the id */
1038 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1039 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1040 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1042 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1044 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1047 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1048 app->data.application.id[0] = 'g'; /* twiddle the id */
1049 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1050 return die_("setting APPLICATION data");
1051 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1052 return die_("copying object");
1053 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1054 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1056 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1059 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1060 app->data.application.id[0] = 'h'; /* twiddle the id */
1061 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1062 return die_("setting APPLICATION data");
1063 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1064 return die_("copying object");
1065 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1066 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1068 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1071 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1072 app->data.application.id[0] = 'i'; /* twiddle the id */
1073 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1074 return die_("setting APPLICATION data");
1075 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1076 return die_("copying object");
1077 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1078 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1079 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1081 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1084 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1085 app->data.application.id[0] = 'j'; /* twiddle the id */
1086 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1087 return die_("setting APPLICATION data");
1088 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1089 return die_("copying object");
1090 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1091 return die_("copying object");
1092 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1093 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1094 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1096 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1099 printf("SVA[A]PP\tnext\n");
1100 if(!FLAC__metadata_simple_iterator_next(iterator))
1101 return die_("iterator ended early\n");
1102 our_current_position++;
1104 printf("SVAA[P]P\tnext\n");
1105 if(!FLAC__metadata_simple_iterator_next(iterator))
1106 return die_("iterator ended early\n");
1107 our_current_position++;
1109 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1110 padding->length = 5;
1111 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1112 return die_("copying object");
1113 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1114 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1116 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1119 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1120 app->data.application.id[0] = 'k'; /* twiddle the id */
1121 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1122 return die_("copying object");
1123 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1124 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1126 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1129 printf("SVAAP[A]\tset PADDING (equal)\n");
1130 padding->length = 27;
1131 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1132 return die_("copying object");
1133 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1134 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1136 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1139 printf("SVAAP[P]\tprev\n");
1140 if(!FLAC__metadata_simple_iterator_prev(iterator))
1141 return die_("iterator ended early\n");
1142 our_current_position--;
1144 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1145 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1146 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1147 delete_from_our_metadata_(our_current_position--);
1149 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1152 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1153 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1154 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1155 delete_from_our_metadata_(our_current_position--);
1157 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1160 printf("SV[A]P\tnext\n");
1161 if(!FLAC__metadata_simple_iterator_next(iterator))
1162 return die_("iterator ended early\n");
1163 our_current_position++;
1165 printf("SVA[P]\tinsert PADDING after\n");
1166 padding->length = 5;
1167 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1168 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1169 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1172 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1175 printf("SVAP[P]\tprev\n");
1176 if(!FLAC__metadata_simple_iterator_prev(iterator))
1177 return die_("iterator ended early\n");
1178 our_current_position--;
1180 printf("SVA[P]P\tprev\n");
1181 if(!FLAC__metadata_simple_iterator_prev(iterator))
1182 return die_("iterator ended early\n");
1183 our_current_position--;
1185 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1186 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1187 return die_("setting APPLICATION data");
1188 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1189 return die_("copying object");
1190 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1191 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1193 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1196 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1197 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1198 return die_("setting APPLICATION data");
1199 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1200 return die_("copying object");
1201 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1202 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1204 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1207 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1208 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1209 return die_("setting APPLICATION data");
1210 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1211 return die_("copying object");
1212 our_metadata_.blocks[our_current_position+1]->length = 0;
1213 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1214 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1216 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1219 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1220 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1221 return die_("setting APPLICATION data");
1222 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1223 return die_("copying object");
1224 delete_from_our_metadata_(our_current_position+1);
1225 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1226 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1228 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1231 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1232 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1233 return die_("setting APPLICATION data");
1234 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1235 return die_("copying object");
1236 delete_from_our_metadata_(our_current_position+1);
1237 our_metadata_.blocks[our_current_position]->is_last = true;
1238 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1239 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1241 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1244 printf("SV[A]\tset PADDING (equal size)\n");
1245 padding->length = app->length;
1246 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1247 return die_("copying object");
1248 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1249 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1251 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1254 printf("SV[P]\tinsert PADDING after\n");
1255 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1256 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1257 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1260 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1263 printf("SVP[P]\tinsert PADDING after\n");
1264 padding->length = 5;
1265 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1266 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1267 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1270 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1273 printf("SVPP[P]\tprev\n");
1274 if(!FLAC__metadata_simple_iterator_prev(iterator))
1275 return die_("iterator ended early\n");
1276 our_current_position--;
1278 printf("SVP[P]P\tprev\n");
1279 if(!FLAC__metadata_simple_iterator_prev(iterator))
1280 return die_("iterator ended early\n");
1281 our_current_position--;
1283 printf("SV[P]PP\tprev\n");
1284 if(!FLAC__metadata_simple_iterator_prev(iterator))
1285 return die_("iterator ended early\n");
1286 our_current_position--;
1288 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1289 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1290 return die_("setting APPLICATION data");
1291 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1292 return die_("copying object");
1293 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1294 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1296 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1299 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1300 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1301 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1302 delete_from_our_metadata_(our_current_position--);
1304 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1307 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1308 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1309 return die_("setting APPLICATION data");
1310 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1311 return die_("copying object");
1312 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1313 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1315 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1318 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1319 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1320 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1321 delete_from_our_metadata_(our_current_position--);
1323 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1326 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1327 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1328 return die_("setting APPLICATION data");
1329 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1330 return die_("copying object");
1331 delete_from_our_metadata_(our_current_position+1);
1332 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1333 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1335 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1338 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1339 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1340 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1341 delete_from_our_metadata_(our_current_position--);
1343 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1346 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1347 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1348 return die_("setting APPLICATION data");
1349 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1350 return die_("copying object");
1351 our_metadata_.blocks[our_current_position+1]->length = 0;
1352 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1353 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1355 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1358 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1359 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1360 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1361 delete_from_our_metadata_(our_current_position--);
1363 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1366 printf("S[V]PP\tnext\n");
1367 if(!FLAC__metadata_simple_iterator_next(iterator))
1368 return die_("iterator ended early\n");
1369 our_current_position++;
1371 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1372 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1373 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1374 delete_from_our_metadata_(our_current_position--);
1376 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1379 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1380 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1381 return die_("setting APPLICATION data");
1382 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1383 return die_("copying object");
1384 delete_from_our_metadata_(our_current_position+1);
1385 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1386 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1388 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1391 printf("delete simple iterator\n");
1393 FLAC__metadata_simple_iterator_delete(iterator);
1395 FLAC__metadata_object_delete(app);
1396 FLAC__metadata_object_delete(padding);
1398 if(!remove_file_(flacfile_))
1404 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1406 FLAC__Metadata_Iterator *iterator;
1407 FLAC__Metadata_Chain *chain;
1408 FLAC__StreamMetadata *block, *app, *padding;
1409 FLAC__byte data[2000];
1410 unsigned our_current_position;
1412 /* initialize 'data' to avoid Valgrind errors */
1413 memset(data, 0, sizeof(data));
1415 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1417 printf("generate read-only file\n");
1419 if(!generate_file_(/*include_extras=*/false))
1422 if(!change_stats_(flacfile_, /*read_only=*/true))
1425 printf("create chain\n");
1427 if(0 == (chain = FLAC__metadata_chain_new()))
1428 return die_("allocating chain");
1430 printf("read chain\n");
1432 if(!read_chain_(chain, flacfile_, filename_based))
1433 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1435 printf("[S]VP\ttest initial metadata\n");
1437 if(!compare_chain_(chain, 0, 0))
1439 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1442 printf("switch file to read-write\n");
1444 if(!change_stats_(flacfile_, /*read-only=*/false))
1447 printf("create iterator\n");
1448 if(0 == (iterator = FLAC__metadata_iterator_new()))
1449 return die_("allocating memory for iterator");
1451 our_current_position = 0;
1453 FLAC__metadata_iterator_init(iterator, chain);
1455 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1456 return die_("getting block from iterator");
1458 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1460 printf("[S]VP\tmodify STREAMINFO, write\n");
1462 block->data.stream_info.sample_rate = 32000;
1463 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1464 return die_("copying object");
1466 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1467 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1468 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1470 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1473 printf("[S]VP\tnext\n");
1474 if(!FLAC__metadata_iterator_next(iterator))
1475 return die_("iterator ended early\n");
1476 our_current_position++;
1478 printf("S[V]P\tnext\n");
1479 if(!FLAC__metadata_iterator_next(iterator))
1480 return die_("iterator ended early\n");
1481 our_current_position++;
1483 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1484 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1485 return die_("getting block from iterator");
1486 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1487 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1488 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1489 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1490 return die_("setting APPLICATION data");
1491 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1492 return die_("copying object");
1493 if(!FLAC__metadata_iterator_set_block(iterator, app))
1494 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1496 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1497 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1498 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1500 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1503 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1504 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1505 return die_("copying object");
1506 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1507 return die_("setting APPLICATION data");
1508 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1509 return die_("copying object");
1510 if(!FLAC__metadata_iterator_set_block(iterator, app))
1511 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1513 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1514 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1515 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1517 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1520 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1521 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1522 return die_("copying object");
1523 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1524 return die_("setting APPLICATION data");
1525 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1526 return die_("copying object");
1527 if(!FLAC__metadata_iterator_set_block(iterator, app))
1528 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1530 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1531 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1532 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1534 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1537 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1538 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1539 return die_("copying object");
1540 if(!FLAC__metadata_object_application_set_data(app, data, 36, 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 if(!FLAC__metadata_iterator_set_block(iterator, app))
1545 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1547 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1548 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1549 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1551 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1554 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1555 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1556 return die_("copying object");
1557 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1558 return die_("setting APPLICATION data");
1559 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1560 return die_("copying object");
1561 if(!FLAC__metadata_iterator_set_block(iterator, app))
1562 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1564 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1565 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1566 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1568 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1571 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1572 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1573 return die_("creating PADDING block");
1574 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1575 return die_("copying object");
1576 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1577 return die_("setting APPLICATION data");
1578 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1579 return die_("copying object");
1580 padding->length = 0;
1581 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1582 return die_("internal error");
1583 if(!FLAC__metadata_iterator_set_block(iterator, app))
1584 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1586 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1587 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1588 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1590 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1593 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1594 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1595 return die_("copying object");
1596 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1597 return die_("setting APPLICATION data");
1598 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1599 return die_("copying object");
1600 our_metadata_.blocks[our_current_position+1]->length = 13;
1601 if(!FLAC__metadata_iterator_set_block(iterator, app))
1602 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1604 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1605 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1606 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1608 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1611 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1612 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1613 return die_("copying object");
1614 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1615 return die_("setting APPLICATION data");
1616 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1617 return die_("copying object");
1618 if(!FLAC__metadata_iterator_set_block(iterator, app))
1619 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1621 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1622 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1623 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1625 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1628 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1629 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1630 return die_("copying object");
1631 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1632 return die_("setting APPLICATION data");
1633 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1634 return die_("copying object");
1635 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1636 if(!FLAC__metadata_iterator_set_block(iterator, app))
1637 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1639 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1640 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1641 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1643 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1646 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1647 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1648 return die_("copying object");
1649 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1650 return die_("setting APPLICATION data");
1651 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1652 return die_("copying object");
1653 delete_from_our_metadata_(our_current_position+1);
1654 if(!FLAC__metadata_iterator_set_block(iterator, app))
1655 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1657 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1658 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1659 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1661 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1664 printf("SV[A]\tprev\n");
1665 if(!FLAC__metadata_iterator_prev(iterator))
1666 return die_("iterator ended early\n");
1667 our_current_position--;
1669 printf("S[V]A\tprev\n");
1670 if(!FLAC__metadata_iterator_prev(iterator))
1671 return die_("iterator ended early\n");
1672 our_current_position--;
1674 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1675 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1676 return die_("creating PADDING block");
1677 padding->length = 30;
1678 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1679 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1681 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1683 printf("[S]VP\tnext\n");
1684 if(!FLAC__metadata_iterator_next(iterator))
1685 return die_("iterator ended early\n");
1686 our_current_position++;
1688 printf("S[V]A\tinsert PADDING after\n");
1689 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1690 return die_("copying metadata");
1691 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1692 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1694 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1697 printf("SV[P]A\tinsert PADDING before\n");
1698 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1699 return die_("creating PADDING block");
1700 padding->length = 17;
1701 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1702 return die_("copying metadata");
1703 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1704 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1706 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1709 printf("SV[P]PA\tinsert PADDING before\n");
1710 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1711 return die_("creating PADDING block");
1712 padding->length = 0;
1713 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1714 return die_("copying metadata");
1715 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1716 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1718 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1721 printf("SV[P]PPA\tnext\n");
1722 if(!FLAC__metadata_iterator_next(iterator))
1723 return die_("iterator ended early\n");
1724 our_current_position++;
1726 printf("SVP[P]PA\tnext\n");
1727 if(!FLAC__metadata_iterator_next(iterator))
1728 return die_("iterator ended early\n");
1729 our_current_position++;
1731 printf("SVPP[P]A\tnext\n");
1732 if(!FLAC__metadata_iterator_next(iterator))
1733 return die_("iterator ended early\n");
1734 our_current_position++;
1736 printf("SVPPP[A]\tinsert PADDING after\n");
1737 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1738 return die_("creating PADDING block");
1739 padding->length = 57;
1740 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1741 return die_("copying metadata");
1742 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1743 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1745 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1748 printf("SVPPPA[P]\tinsert PADDING before\n");
1749 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1750 return die_("creating PADDING block");
1751 padding->length = 99;
1752 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1753 return die_("copying metadata");
1754 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1755 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1757 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1760 printf("delete iterator\n");
1761 FLAC__metadata_iterator_delete(iterator);
1762 our_current_position = 0;
1764 printf("SVPPPAPP\tmerge padding\n");
1765 FLAC__metadata_chain_merge_padding(chain);
1766 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1767 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1768 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1769 delete_from_our_metadata_(7);
1770 delete_from_our_metadata_(4);
1771 delete_from_our_metadata_(3);
1773 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1774 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1775 if(!compare_chain_(chain, 0, 0))
1777 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1780 printf("SVPAP\tsort padding\n");
1781 FLAC__metadata_chain_sort_padding(chain);
1782 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1783 delete_from_our_metadata_(2);
1785 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1786 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1787 if(!compare_chain_(chain, 0, 0))
1789 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1792 printf("create iterator\n");
1793 if(0 == (iterator = FLAC__metadata_iterator_new()))
1794 return die_("allocating memory for iterator");
1796 our_current_position = 0;
1798 FLAC__metadata_iterator_init(iterator, chain);
1800 printf("[S]VAP\tnext\n");
1801 if(!FLAC__metadata_iterator_next(iterator))
1802 return die_("iterator ended early\n");
1803 our_current_position++;
1805 printf("S[V]AP\tnext\n");
1806 if(!FLAC__metadata_iterator_next(iterator))
1807 return die_("iterator ended early\n");
1808 our_current_position++;
1810 printf("SV[A]P\tdelete middle block, replace with padding\n");
1811 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1812 return die_("creating PADDING block");
1813 padding->length = 71;
1814 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1815 return die_("copying object");
1816 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1817 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1819 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1822 printf("S[V]PP\tnext\n");
1823 if(!FLAC__metadata_iterator_next(iterator))
1824 return die_("iterator ended early\n");
1825 our_current_position++;
1827 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1828 delete_from_our_metadata_(our_current_position--);
1829 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1830 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1832 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1835 printf("S[V]P\tnext\n");
1836 if(!FLAC__metadata_iterator_next(iterator))
1837 return die_("iterator ended early\n");
1838 our_current_position++;
1840 printf("SV[P]\tdelete last block, replace with padding\n");
1841 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1842 return die_("creating PADDING block");
1843 padding->length = 219;
1844 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1845 return die_("copying object");
1846 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1847 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1849 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1852 printf("S[V]P\tnext\n");
1853 if(!FLAC__metadata_iterator_next(iterator))
1854 return die_("iterator ended early\n");
1855 our_current_position++;
1857 printf("SV[P]\tdelete last block, don't replace with padding\n");
1858 delete_from_our_metadata_(our_current_position--);
1859 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1860 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1862 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1865 printf("S[V]\tprev\n");
1866 if(!FLAC__metadata_iterator_prev(iterator))
1867 return die_("iterator ended early\n");
1868 our_current_position--;
1870 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1871 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1872 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1874 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1877 printf("delete iterator\n");
1878 FLAC__metadata_iterator_delete(iterator);
1879 our_current_position = 0;
1881 printf("SV\tmerge padding\n");
1882 FLAC__metadata_chain_merge_padding(chain);
1884 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1885 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1886 if(!compare_chain_(chain, 0, 0))
1888 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1891 printf("SV\tsort padding\n");
1892 FLAC__metadata_chain_sort_padding(chain);
1894 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1895 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1896 if(!compare_chain_(chain, 0, 0))
1898 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1901 printf("delete chain\n");
1903 FLAC__metadata_chain_delete(chain);
1905 if(!remove_file_(flacfile_))
1911 static FLAC__bool test_level_2_misc_()
1913 FLAC__Metadata_Iterator *iterator;
1914 FLAC__Metadata_Chain *chain;
1915 FLAC__IOCallbacks callbacks;
1917 memset(&callbacks, 0, sizeof(callbacks));
1918 callbacks.read = (FLAC__IOCallback_Read)fread;
1919 #ifdef FLAC__VALGRIND_TESTING
1920 callbacks.write = chain_write_cb_;
1922 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1924 callbacks.seek = chain_seek_cb_;
1925 callbacks.tell = chain_tell_cb_;
1926 callbacks.eof = chain_eof_cb_;
1928 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1930 printf("generate file\n");
1932 if(!generate_file_(/*include_extras=*/false))
1935 printf("create chain\n");
1937 if(0 == (chain = FLAC__metadata_chain_new()))
1938 return die_("allocating chain");
1940 printf("read chain (filename-based)\n");
1942 if(!FLAC__metadata_chain_read(chain, flacfile_))
1943 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1945 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1947 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1948 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1949 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1950 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1951 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1954 printf("read chain (filename-based)\n");
1956 if(!FLAC__metadata_chain_read(chain, flacfile_))
1957 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1959 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1961 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1962 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1963 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1964 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1965 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1968 printf("read chain (callback-based)\n");
1970 FILE *file = fopen(flacfile_, "rb");
1972 return die_("opening file");
1973 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1975 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1980 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1982 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1983 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1984 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1985 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1986 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1989 printf("read chain (callback-based)\n");
1991 FILE *file = fopen(flacfile_, "rb");
1993 return die_("opening file");
1994 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1996 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2001 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2003 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2004 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2006 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2008 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2010 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2011 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2012 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2013 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2014 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2017 printf("read chain (callback-based)\n");
2019 FILE *file = fopen(flacfile_, "rb");
2021 return die_("opening file");
2022 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2024 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2029 printf("create iterator\n");
2030 if(0 == (iterator = FLAC__metadata_iterator_new()))
2031 return die_("allocating memory for iterator");
2033 FLAC__metadata_iterator_init(iterator, chain);
2035 printf("[S]VP\tnext\n");
2036 if(!FLAC__metadata_iterator_next(iterator))
2037 return die_("iterator ended early\n");
2039 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2040 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2041 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2043 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2045 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2046 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2048 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2050 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2052 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2053 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2054 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2055 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2056 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2059 printf("delete iterator\n");
2061 FLAC__metadata_iterator_delete(iterator);
2063 printf("delete chain\n");
2065 FLAC__metadata_chain_delete(chain);
2067 if(!remove_file_(flacfile_))
2073 FLAC__bool test_metadata_file_manipulation()
2075 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2077 our_metadata_.num_blocks = 0;
2079 if(!test_level_0_())
2082 if(!test_level_1_())
2085 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2087 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2089 if(!test_level_2_misc_())