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 "file_utils.h"
38 #include "metadata_utils.h"
39 #include "FLAC/assert.h"
40 #include "FLAC/file_decoder.h"
41 #include "FLAC/metadata.h"
42 #include "share/grabbag.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__FileDecoder 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 /* functions for working with our metadata copy */
105 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
108 FLAC__StreamMetadata *obj = block;
109 FLAC__ASSERT(position < our_metadata_.num_blocks);
111 if(0 == (obj = FLAC__metadata_object_clone(block)))
112 return die_("during FLAC__metadata_object_clone()");
114 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
115 our_metadata_.blocks[position] = obj;
117 /* set the is_last flags */
118 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
119 our_metadata_.blocks[i]->is_last = false;
120 our_metadata_.blocks[i]->is_last = true;
125 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
128 FLAC__StreamMetadata *obj = block;
130 if(0 == (obj = FLAC__metadata_object_clone(block)))
131 return die_("during FLAC__metadata_object_clone()");
133 if(position > our_metadata_.num_blocks) {
134 position = our_metadata_.num_blocks;
137 for(i = our_metadata_.num_blocks; i > position; i--)
138 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
140 our_metadata_.blocks[position] = obj;
141 our_metadata_.num_blocks++;
143 /* set the is_last flags */
144 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
145 our_metadata_.blocks[i]->is_last = false;
146 our_metadata_.blocks[i]->is_last = true;
151 static void delete_from_our_metadata_(unsigned position)
154 FLAC__ASSERT(position < our_metadata_.num_blocks);
155 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
156 for(i = position; i < our_metadata_.num_blocks - 1; i++)
157 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
158 our_metadata_.num_blocks--;
160 /* set the is_last flags */
161 if(our_metadata_.num_blocks > 0) {
162 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
163 our_metadata_.blocks[i]->is_last = false;
164 our_metadata_.blocks[i]->is_last = true;
169 * This wad of functions supports filename- and callback-based chain reading/writing.
170 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
172 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
174 static const char *tempfile_suffix = ".metadata_edit";
176 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
178 strcpy(*tempfilename, filename);
179 strcat(*tempfilename, tempfile_suffix);
181 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
187 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
190 (void)fclose(*tempfile);
194 if(0 != *tempfilename) {
195 (void)unlink(*tempfilename);
201 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
203 FLAC__ASSERT(0 != filename);
204 FLAC__ASSERT(0 != tempfile);
205 FLAC__ASSERT(0 != tempfilename);
206 FLAC__ASSERT(0 != *tempfilename);
209 (void)fclose(*tempfile);
213 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
214 if(unlink(filename) < 0) {
215 cleanup_tempfile_(tempfile, tempfilename);
220 if(0 != rename(*tempfilename, filename)) {
221 cleanup_tempfile_(tempfile, tempfilename);
225 cleanup_tempfile_(tempfile, tempfilename);
230 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
232 FLAC__ASSERT(0 != filename);
233 FLAC__ASSERT(0 != stats);
234 return (0 == stat(filename, stats));
237 void set_file_stats_(const char *filename, struct stat *stats)
239 struct utimbuf srctime;
241 FLAC__ASSERT(0 != filename);
242 FLAC__ASSERT(0 != stats);
244 srctime.actime = stats->st_atime;
245 srctime.modtime = stats->st_mtime;
246 (void)chmod(filename, stats->st_mode);
247 (void)utime(filename, &srctime);
248 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
249 (void)chown(filename, stats->st_uid, -1);
250 (void)chown(filename, -1, stats->st_gid);
254 #ifdef FLAC__VALGRIND_TESTING
255 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
257 FILE *stream = (FILE*)handle;
258 size_t ret = fwrite(ptr, size, nmemb, stream);
265 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
267 off_t o = (off_t)offset;
268 FLAC__ASSERT(offset == o);
269 return fseeko((FILE*)handle, o, whence);
272 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
274 return ftello((FILE*)handle);
277 static int chain_eof_cb_(FLAC__IOHandle handle)
279 return feof((FILE*)handle);
282 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)
285 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
287 FLAC__IOCallbacks callbacks;
289 memset(&callbacks, 0, sizeof(callbacks));
290 callbacks.read = (FLAC__IOCallback_Read)fread;
291 #ifdef FLAC__VALGRIND_TESTING
292 callbacks.write = chain_write_cb_;
294 callbacks.write = (FLAC__IOCallback_Write)fwrite;
296 callbacks.seek = chain_seek_cb_;
297 callbacks.eof = chain_eof_cb_;
299 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
301 FILE *file, *tempfile;
303 if(preserve_file_stats) {
304 if(!get_file_stats_(filename, &stats))
307 if(0 == (file = fopen(filename, "rb")))
308 return false; /*@@@ chain status still says OK though */
309 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
311 cleanup_tempfile_(&tempfile, &tempfilename);
312 return false; /*@@@ chain status still says OK though */
314 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
322 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
324 if(preserve_file_stats)
325 set_file_stats_(filename, &stats);
328 FILE *file = fopen(filename, "r+b");
330 return false; /*@@@ chain status still says OK though */
331 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
340 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
343 return FLAC__metadata_chain_read(chain, flacfile_);
345 FLAC__IOCallbacks callbacks;
347 memset(&callbacks, 0, sizeof(callbacks));
348 callbacks.read = (FLAC__IOCallback_Read)fread;
349 callbacks.seek = chain_seek_cb_;
350 callbacks.tell = chain_tell_cb_;
354 FILE *file = fopen(filename, "rb");
356 return false; /*@@@ chain status still says OK though */
357 ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
364 /* function for comparing our metadata to a FLAC__Metadata_Chain */
366 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
369 FLAC__Metadata_Iterator *iterator;
370 FLAC__StreamMetadata *block;
371 FLAC__bool next_ok = true;
373 FLAC__ASSERT(0 != chain);
375 printf("\tcomparing chain... ");
378 if(0 == (iterator = FLAC__metadata_iterator_new()))
379 return die_("allocating memory for iterator");
381 FLAC__metadata_iterator_init(iterator, chain);
388 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
389 FLAC__metadata_iterator_delete(iterator);
390 return die_("getting block from iterator");
393 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
394 FLAC__metadata_iterator_delete(iterator);
395 return die_("metadata block mismatch");
399 next_ok = FLAC__metadata_iterator_next(iterator);
400 } while(i < our_metadata_.num_blocks && next_ok);
402 FLAC__metadata_iterator_delete(iterator);
405 return die_("chain has more blocks than expected");
407 if(i < our_metadata_.num_blocks)
408 return die_("short block count in chain");
410 if(0 != current_block) {
411 printf("CURRENT_POSITION... ");
414 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
415 return die_("metadata block mismatch");
423 /* decoder callbacks for checking the file */
425 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
427 (void)decoder, (void)buffer, (void)client_data;
430 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
431 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
433 printf("content... ");
437 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
440 /* this version pays no attention to the metadata */
441 static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
443 (void)decoder, (void)metadata, (void)client_data;
445 printf("%d... ", mc_our_block_number_);
448 mc_our_block_number_++;
451 /* this version is used when we want to compare to our metadata copy */
452 static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
454 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
458 /* don't bother checking if we've already hit an error */
459 if(dcd->error_occurred)
462 printf("%d... ", mc_our_block_number_);
465 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
466 (void)die_("got more metadata blocks than expected");
467 dcd->error_occurred = true;
470 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
471 (void)die_("metadata block mismatch");
472 dcd->error_occurred = true;
475 mc_our_block_number_++;
478 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
480 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
483 dcd->error_occurred = true;
484 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
487 static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
489 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
490 FLAC__StreamMetadata *metadata[3];
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 = 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");
537 padding.is_last = true;
538 padding.type = FLAC__METADATA_TYPE_PADDING;
539 padding.length = 1234;
541 metadata[n++] = &vorbiscomment;
542 if (include_cuesheet)
543 metadata[n++] = cuesheet;
544 metadata[n++] = &padding;
547 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
548 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
549 (include_cuesheet && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
550 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
552 return die_("priming our metadata");
554 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
555 return die_("creating the encoded file");
557 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
562 static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
564 FLAC__FileDecoder *decoder;
565 decoder_client_struct decoder_client_data;
567 FLAC__ASSERT(0 != filename);
568 FLAC__ASSERT(0 != metadata_callback);
570 mc_our_block_number_ = 0;
571 decoder_client_data.error_occurred = false;
573 printf("\ttesting '%s'... ", filename);
576 if(0 == (decoder = FLAC__file_decoder_new()))
577 return die_("couldn't allocate decoder instance");
579 FLAC__file_decoder_set_md5_checking(decoder, true);
580 FLAC__file_decoder_set_filename(decoder, filename);
581 FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
582 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
583 FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
584 FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
585 FLAC__file_decoder_set_metadata_respond_all(decoder);
586 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
587 FLAC__file_decoder_finish(decoder);
588 FLAC__file_decoder_delete(decoder);
589 return die_("initializing decoder\n");
591 if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
592 FLAC__file_decoder_finish(decoder);
593 FLAC__file_decoder_delete(decoder);
594 return die_("decoding file\n");
597 FLAC__file_decoder_finish(decoder);
598 FLAC__file_decoder_delete(decoder);
600 if(decoder_client_data.error_occurred)
603 if(mc_our_block_number_ != our_metadata_.num_blocks)
604 return die_("short metadata block count");
610 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
612 if(!grabbag__file_change_stats(filename, read_only))
613 return die_("during grabbag__file_change_stats()");
618 static FLAC__bool remove_file_(const char *filename)
620 while(our_metadata_.num_blocks > 0)
621 delete_from_our_metadata_(0);
623 if(!grabbag__file_remove_file(filename))
624 return die_("removing file");
629 static FLAC__bool test_level_0_()
631 FLAC__StreamMetadata streaminfo;
632 FLAC__StreamMetadata *tags = 0;
633 FLAC__StreamMetadata *cuesheet = 0;
635 printf("\n\n++++++ testing level 0 interface\n");
637 if(!generate_file_(/*include_cuesheet=*/true))
640 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
643 printf("testing FLAC__metadata_get_streaminfo()... ");
645 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
646 return die_("during FLAC__metadata_get_streaminfo()");
648 /* check to see if some basic data matches (c.f. generate_file_()) */
649 if(streaminfo.data.stream_info.channels != 1)
650 return die_("mismatch in streaminfo.data.stream_info.channels");
651 if(streaminfo.data.stream_info.bits_per_sample != 8)
652 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
653 if(streaminfo.data.stream_info.sample_rate != 44100)
654 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
655 if(streaminfo.data.stream_info.min_blocksize != 576)
656 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
657 if(streaminfo.data.stream_info.max_blocksize != 576)
658 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
662 printf("testing FLAC__metadata_get_tags()... ");
664 if(!FLAC__metadata_get_tags(flacfile_, &tags))
665 return die_("during FLAC__metadata_get_tags()");
667 /* check to see if some basic data matches (c.f. generate_file_()) */
668 if(tags->data.vorbis_comment.num_comments != 0)
669 return die_("mismatch in tags->data.vorbis_comment.num_comments");
673 FLAC__metadata_object_delete(tags);
675 printf("testing FLAC__metadata_get_cuesheet()... ");
677 if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
678 return die_("during FLAC__metadata_get_cuesheet()");
680 /* check to see if some basic data matches (c.f. generate_file_()) */
681 if(cuesheet->data.cue_sheet.lead_in != 123)
682 return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
686 FLAC__metadata_object_delete(cuesheet);
688 if(!remove_file_(flacfile_))
694 static FLAC__bool test_level_1_()
696 FLAC__Metadata_SimpleIterator *iterator;
697 FLAC__StreamMetadata *block, *app, *padding;
698 FLAC__byte data[1000];
699 unsigned our_current_position = 0;
701 /* initialize 'data' to avoid Valgrind errors */
702 memset(data, 0, sizeof(data));
704 printf("\n\n++++++ testing level 1 interface\n");
706 /************************************************************/
708 printf("simple iterator on read-only file\n");
710 if(!generate_file_(/*include_cuesheet=*/false))
713 if(!change_stats_(flacfile_, /*read_only=*/true))
716 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
719 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
720 return die_("FLAC__metadata_simple_iterator_new()");
722 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
723 return die_("FLAC__metadata_simple_iterator_init() returned false");
725 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
726 if(FLAC__metadata_simple_iterator_is_writable(iterator))
727 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
729 printf("iterate forwards\n");
731 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
732 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
733 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
734 return die_("getting block 0");
735 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
736 return die_("expected STREAMINFO type");
738 return die_("expected is_last to be false");
739 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
740 return die_("bad STREAMINFO length");
741 /* check to see if some basic data matches (c.f. generate_file_()) */
742 if(block->data.stream_info.channels != 1)
743 return die_("mismatch in channels");
744 if(block->data.stream_info.bits_per_sample != 8)
745 return die_("mismatch in bits_per_sample");
746 if(block->data.stream_info.sample_rate != 44100)
747 return die_("mismatch in sample_rate");
748 if(block->data.stream_info.min_blocksize != 576)
749 return die_("mismatch in min_blocksize");
750 if(block->data.stream_info.max_blocksize != 576)
751 return die_("mismatch in max_blocksize");
752 FLAC__metadata_object_delete(block);
754 if(!FLAC__metadata_simple_iterator_next(iterator))
755 return die_("forward iterator ended early");
756 our_current_position++;
758 if(!FLAC__metadata_simple_iterator_next(iterator))
759 return die_("forward iterator ended early");
760 our_current_position++;
762 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
763 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
764 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
765 return die_("getting block 2");
766 if(block->type != FLAC__METADATA_TYPE_PADDING)
767 return die_("expected PADDING type");
769 return die_("expected is_last to be true");
770 /* check to see if some basic data matches (c.f. generate_file_()) */
771 if(block->length != 1234)
772 return die_("bad PADDING length");
773 FLAC__metadata_object_delete(block);
775 if(FLAC__metadata_simple_iterator_next(iterator))
776 return die_("forward iterator returned true but should have returned false");
778 printf("iterate backwards\n");
779 if(!FLAC__metadata_simple_iterator_prev(iterator))
780 return die_("reverse iterator ended early");
781 if(!FLAC__metadata_simple_iterator_prev(iterator))
782 return die_("reverse iterator ended early");
783 if(FLAC__metadata_simple_iterator_prev(iterator))
784 return die_("reverse iterator returned true but should have returned false");
786 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
788 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
789 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
791 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
793 FLAC__metadata_simple_iterator_delete(iterator);
795 /************************************************************/
797 printf("simple iterator on writable file\n");
799 if(!change_stats_(flacfile_, /*read-only=*/false))
802 printf("creating APPLICATION block\n");
804 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
805 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
806 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
808 printf("creating PADDING block\n");
810 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
811 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
812 padding->length = 20;
814 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
815 return die_("FLAC__metadata_simple_iterator_new()");
817 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
818 return die_("FLAC__metadata_simple_iterator_init() returned false");
819 our_current_position = 0;
821 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
823 printf("[S]VP\ttry to write over STREAMINFO block...\n");
824 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
825 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
827 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
829 printf("[S]VP\tnext\n");
830 if(!FLAC__metadata_simple_iterator_next(iterator))
831 return die_("iterator ended early\n");
832 our_current_position++;
834 printf("S[V]P\tnext\n");
835 if(!FLAC__metadata_simple_iterator_next(iterator))
836 return die_("iterator ended early\n");
837 our_current_position++;
839 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
840 padding->length = 25;
841 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
842 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
843 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
846 printf("SVP[P]\tprev\n");
847 if(!FLAC__metadata_simple_iterator_prev(iterator))
848 return die_("iterator ended early\n");
849 our_current_position--;
851 printf("SV[P]P\tprev\n");
852 if(!FLAC__metadata_simple_iterator_prev(iterator))
853 return die_("iterator ended early\n");
854 our_current_position--;
856 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
857 padding->length = 30;
858 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
859 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
860 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
863 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
866 printf("SV[P]PP\tprev\n");
867 if(!FLAC__metadata_simple_iterator_prev(iterator))
868 return die_("iterator ended early\n");
869 our_current_position--;
871 printf("S[V]PPP\tprev\n");
872 if(!FLAC__metadata_simple_iterator_prev(iterator))
873 return die_("iterator ended early\n");
874 our_current_position--;
876 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
877 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
878 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
880 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
883 printf("[S]VPPP\tnext\n");
884 if(!FLAC__metadata_simple_iterator_next(iterator))
885 return die_("iterator ended early\n");
886 our_current_position++;
888 printf("S[V]PPP\tnext\n");
889 if(!FLAC__metadata_simple_iterator_next(iterator))
890 return die_("iterator ended early\n");
891 our_current_position++;
893 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
894 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
895 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
896 our_current_position--;
898 printf("S[V]PPP\tnext\n");
899 if(!FLAC__metadata_simple_iterator_next(iterator))
900 return die_("iterator ended early\n");
901 our_current_position++;
903 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
904 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
905 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
906 delete_from_our_metadata_(our_current_position--);
908 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
911 printf("S[V]PP\tnext\n");
912 if(!FLAC__metadata_simple_iterator_next(iterator))
913 return die_("iterator ended early\n");
914 our_current_position++;
916 printf("SV[P]P\tnext\n");
917 if(!FLAC__metadata_simple_iterator_next(iterator))
918 return die_("iterator ended early\n");
919 our_current_position++;
921 printf("SVP[P]\tdelete (last block), replace with padding\n");
922 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
923 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
924 our_current_position--;
926 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
929 printf("SV[P]P\tnext\n");
930 if(!FLAC__metadata_simple_iterator_next(iterator))
931 return die_("iterator ended early\n");
932 our_current_position++;
934 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
935 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
936 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
937 delete_from_our_metadata_(our_current_position--);
939 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
942 printf("SV[P]\tprev\n");
943 if(!FLAC__metadata_simple_iterator_prev(iterator))
944 return die_("iterator ended early\n");
945 our_current_position--;
947 printf("S[V]P\tprev\n");
948 if(!FLAC__metadata_simple_iterator_prev(iterator))
949 return die_("iterator ended early\n");
950 our_current_position--;
952 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
953 FLAC__ASSERT(our_current_position == 0);
954 block = FLAC__metadata_simple_iterator_get_block(iterator);
955 block->data.stream_info.sample_rate = 32000;
956 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
957 return die_("copying object");
958 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
959 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
960 FLAC__metadata_object_delete(block);
962 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
965 printf("[S]VP\tnext\n");
966 if(!FLAC__metadata_simple_iterator_next(iterator))
967 return die_("iterator ended early\n");
968 our_current_position++;
970 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
971 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
972 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
973 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
974 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
976 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
978 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
981 printf("SV[A]P\tnext\n");
982 if(!FLAC__metadata_simple_iterator_next(iterator))
983 return die_("iterator ended early\n");
984 our_current_position++;
986 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
987 app->data.application.id[0] = 'f'; /* twiddle the id */
988 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
989 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
990 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
992 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
994 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
997 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
998 app->data.application.id[0] = 'g'; /* twiddle the id */
999 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1000 return die_("setting APPLICATION data");
1001 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1002 return die_("copying object");
1003 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1004 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1006 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1009 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1010 app->data.application.id[0] = 'h'; /* twiddle the id */
1011 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1012 return die_("setting APPLICATION data");
1013 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1014 return die_("copying object");
1015 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1016 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1018 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1021 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1022 app->data.application.id[0] = 'i'; /* twiddle the id */
1023 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1024 return die_("setting APPLICATION data");
1025 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1026 return die_("copying object");
1027 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1028 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1029 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1031 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1034 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1035 app->data.application.id[0] = 'j'; /* twiddle the id */
1036 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1037 return die_("setting APPLICATION data");
1038 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1039 return die_("copying object");
1040 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1041 return die_("copying object");
1042 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1043 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1044 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1046 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1049 printf("SVA[A]PP\tnext\n");
1050 if(!FLAC__metadata_simple_iterator_next(iterator))
1051 return die_("iterator ended early\n");
1052 our_current_position++;
1054 printf("SVAA[P]P\tnext\n");
1055 if(!FLAC__metadata_simple_iterator_next(iterator))
1056 return die_("iterator ended early\n");
1057 our_current_position++;
1059 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1060 padding->length = 5;
1061 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1062 return die_("copying object");
1063 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1064 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1066 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1069 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1070 app->data.application.id[0] = 'k'; /* twiddle the id */
1071 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1072 return die_("copying object");
1073 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1074 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1076 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1079 printf("SVAAP[A]\tset PADDING (equal)\n");
1080 padding->length = 27;
1081 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1082 return die_("copying object");
1083 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1084 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1086 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1089 printf("SVAAP[P]\tprev\n");
1090 if(!FLAC__metadata_simple_iterator_prev(iterator))
1091 return die_("iterator ended early\n");
1092 our_current_position--;
1094 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1095 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1096 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1097 delete_from_our_metadata_(our_current_position--);
1099 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1102 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1103 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1104 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1105 delete_from_our_metadata_(our_current_position--);
1107 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1110 printf("SV[A]P\tnext\n");
1111 if(!FLAC__metadata_simple_iterator_next(iterator))
1112 return die_("iterator ended early\n");
1113 our_current_position++;
1115 printf("SVA[P]\tinsert PADDING after\n");
1116 padding->length = 5;
1117 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1118 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1119 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1122 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1125 printf("SVAP[P]\tprev\n");
1126 if(!FLAC__metadata_simple_iterator_prev(iterator))
1127 return die_("iterator ended early\n");
1128 our_current_position--;
1130 printf("SVA[P]P\tprev\n");
1131 if(!FLAC__metadata_simple_iterator_prev(iterator))
1132 return die_("iterator ended early\n");
1133 our_current_position--;
1135 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1136 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1137 return die_("setting APPLICATION data");
1138 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1139 return die_("copying object");
1140 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1141 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1143 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1146 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1147 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1148 return die_("setting APPLICATION data");
1149 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1150 return die_("copying object");
1151 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1152 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1154 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1157 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1158 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1159 return die_("setting APPLICATION data");
1160 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1161 return die_("copying object");
1162 our_metadata_.blocks[our_current_position+1]->length = 0;
1163 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1164 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1166 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1169 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1170 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1171 return die_("setting APPLICATION data");
1172 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1173 return die_("copying object");
1174 delete_from_our_metadata_(our_current_position+1);
1175 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1176 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1178 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1181 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1182 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1183 return die_("setting APPLICATION data");
1184 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1185 return die_("copying object");
1186 delete_from_our_metadata_(our_current_position+1);
1187 our_metadata_.blocks[our_current_position]->is_last = true;
1188 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1189 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1191 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1194 printf("SV[A]\tset PADDING (equal size)\n");
1195 padding->length = app->length;
1196 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1197 return die_("copying object");
1198 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1199 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1201 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1204 printf("SV[P]\tinsert PADDING after\n");
1205 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1206 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1207 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1210 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1213 printf("SVP[P]\tinsert PADDING after\n");
1214 padding->length = 5;
1215 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1216 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1217 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1220 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1223 printf("SVPP[P]\tprev\n");
1224 if(!FLAC__metadata_simple_iterator_prev(iterator))
1225 return die_("iterator ended early\n");
1226 our_current_position--;
1228 printf("SVP[P]P\tprev\n");
1229 if(!FLAC__metadata_simple_iterator_prev(iterator))
1230 return die_("iterator ended early\n");
1231 our_current_position--;
1233 printf("SV[P]PP\tprev\n");
1234 if(!FLAC__metadata_simple_iterator_prev(iterator))
1235 return die_("iterator ended early\n");
1236 our_current_position--;
1238 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1239 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1240 return die_("setting APPLICATION data");
1241 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1242 return die_("copying object");
1243 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1244 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1246 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1249 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1250 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1251 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1252 delete_from_our_metadata_(our_current_position--);
1254 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1257 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1258 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1259 return die_("setting APPLICATION data");
1260 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1261 return die_("copying object");
1262 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1263 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1265 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1268 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1269 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1270 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1271 delete_from_our_metadata_(our_current_position--);
1273 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1276 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1277 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1278 return die_("setting APPLICATION data");
1279 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1280 return die_("copying object");
1281 delete_from_our_metadata_(our_current_position+1);
1282 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1283 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1285 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1288 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1289 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1290 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1291 delete_from_our_metadata_(our_current_position--);
1293 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1296 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1297 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1298 return die_("setting APPLICATION data");
1299 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1300 return die_("copying object");
1301 our_metadata_.blocks[our_current_position+1]->length = 0;
1302 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1303 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1305 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1308 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1309 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1310 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1311 delete_from_our_metadata_(our_current_position--);
1313 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1316 printf("S[V]PP\tnext\n");
1317 if(!FLAC__metadata_simple_iterator_next(iterator))
1318 return die_("iterator ended early\n");
1319 our_current_position++;
1321 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1322 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1323 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1324 delete_from_our_metadata_(our_current_position--);
1326 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1329 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1330 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1331 return die_("setting APPLICATION data");
1332 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1333 return die_("copying object");
1334 delete_from_our_metadata_(our_current_position+1);
1335 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1336 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1338 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1341 printf("delete simple iterator\n");
1343 FLAC__metadata_simple_iterator_delete(iterator);
1345 FLAC__metadata_object_delete(app);
1346 FLAC__metadata_object_delete(padding);
1348 if(!remove_file_(flacfile_))
1354 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1356 FLAC__Metadata_Iterator *iterator;
1357 FLAC__Metadata_Chain *chain;
1358 FLAC__StreamMetadata *block, *app, *padding;
1359 FLAC__byte data[2000];
1360 unsigned our_current_position;
1362 /* initialize 'data' to avoid Valgrind errors */
1363 memset(data, 0, sizeof(data));
1365 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1367 printf("generate read-only file\n");
1369 if(!generate_file_(/*include_cuesheet=*/false))
1372 if(!change_stats_(flacfile_, /*read_only=*/true))
1375 printf("create chain\n");
1377 if(0 == (chain = FLAC__metadata_chain_new()))
1378 return die_("allocating chain");
1380 printf("read chain\n");
1382 if(!read_chain_(chain, flacfile_, filename_based))
1383 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1385 printf("[S]VP\ttest initial metadata\n");
1387 if(!compare_chain_(chain, 0, 0))
1389 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1392 printf("switch file to read-write\n");
1394 if(!change_stats_(flacfile_, /*read-only=*/false))
1397 printf("create iterator\n");
1398 if(0 == (iterator = FLAC__metadata_iterator_new()))
1399 return die_("allocating memory for iterator");
1401 our_current_position = 0;
1403 FLAC__metadata_iterator_init(iterator, chain);
1405 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1406 return die_("getting block from iterator");
1408 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1410 printf("[S]VP\tmodify STREAMINFO, write\n");
1412 block->data.stream_info.sample_rate = 32000;
1413 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1414 return die_("copying object");
1416 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1417 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1418 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1420 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1423 printf("[S]VP\tnext\n");
1424 if(!FLAC__metadata_iterator_next(iterator))
1425 return die_("iterator ended early\n");
1426 our_current_position++;
1428 printf("S[V]P\tnext\n");
1429 if(!FLAC__metadata_iterator_next(iterator))
1430 return die_("iterator ended early\n");
1431 our_current_position++;
1433 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1434 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1435 return die_("getting block from iterator");
1436 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1437 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1438 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1439 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1440 return die_("setting APPLICATION data");
1441 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1442 return die_("copying object");
1443 if(!FLAC__metadata_iterator_set_block(iterator, app))
1444 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1446 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1447 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1448 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1450 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1453 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1454 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1455 return die_("copying object");
1456 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1457 return die_("setting APPLICATION data");
1458 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1459 return die_("copying object");
1460 if(!FLAC__metadata_iterator_set_block(iterator, app))
1461 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1463 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1464 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1465 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1467 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1470 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1471 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1472 return die_("copying object");
1473 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1474 return die_("setting APPLICATION data");
1475 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1476 return die_("copying object");
1477 if(!FLAC__metadata_iterator_set_block(iterator, app))
1478 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1480 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1481 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1482 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1484 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1487 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1488 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1489 return die_("copying object");
1490 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1491 return die_("setting APPLICATION data");
1492 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1493 return die_("copying object");
1494 if(!FLAC__metadata_iterator_set_block(iterator, app))
1495 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1497 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1498 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1499 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1501 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1504 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1505 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1506 return die_("copying object");
1507 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1508 return die_("setting APPLICATION data");
1509 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1510 return die_("copying object");
1511 if(!FLAC__metadata_iterator_set_block(iterator, app))
1512 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1514 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1515 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1516 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1518 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1521 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1522 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1523 return die_("creating PADDING block");
1524 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1525 return die_("copying object");
1526 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1527 return die_("setting APPLICATION data");
1528 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1529 return die_("copying object");
1530 padding->length = 0;
1531 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1532 return die_("internal error");
1533 if(!FLAC__metadata_iterator_set_block(iterator, app))
1534 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1536 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1537 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1538 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1540 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1543 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1544 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1545 return die_("copying object");
1546 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1547 return die_("setting APPLICATION data");
1548 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1549 return die_("copying object");
1550 our_metadata_.blocks[our_current_position+1]->length = 13;
1551 if(!FLAC__metadata_iterator_set_block(iterator, app))
1552 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1554 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1555 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1556 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1558 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1561 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1562 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1563 return die_("copying object");
1564 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1565 return die_("setting APPLICATION data");
1566 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1567 return die_("copying object");
1568 if(!FLAC__metadata_iterator_set_block(iterator, app))
1569 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1571 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1572 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1573 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1575 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1578 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1579 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1580 return die_("copying object");
1581 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1582 return die_("setting APPLICATION data");
1583 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1584 return die_("copying object");
1585 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1586 if(!FLAC__metadata_iterator_set_block(iterator, app))
1587 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1589 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1590 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1591 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1593 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1596 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1597 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1598 return die_("copying object");
1599 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1600 return die_("setting APPLICATION data");
1601 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1602 return die_("copying object");
1603 delete_from_our_metadata_(our_current_position+1);
1604 if(!FLAC__metadata_iterator_set_block(iterator, app))
1605 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1607 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1608 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1609 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1611 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1614 printf("SV[A]\tprev\n");
1615 if(!FLAC__metadata_iterator_prev(iterator))
1616 return die_("iterator ended early\n");
1617 our_current_position--;
1619 printf("S[V]A\tprev\n");
1620 if(!FLAC__metadata_iterator_prev(iterator))
1621 return die_("iterator ended early\n");
1622 our_current_position--;
1624 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1625 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1626 return die_("creating PADDING block");
1627 padding->length = 30;
1628 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1629 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1631 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1633 printf("[S]VP\tnext\n");
1634 if(!FLAC__metadata_iterator_next(iterator))
1635 return die_("iterator ended early\n");
1636 our_current_position++;
1638 printf("S[V]A\tinsert PADDING after\n");
1639 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1640 return die_("copying metadata");
1641 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1642 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1644 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1647 printf("SV[P]A\tinsert PADDING before\n");
1648 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1649 return die_("creating PADDING block");
1650 padding->length = 17;
1651 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1652 return die_("copying metadata");
1653 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1654 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1656 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1659 printf("SV[P]PA\tinsert PADDING before\n");
1660 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1661 return die_("creating PADDING block");
1662 padding->length = 0;
1663 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1664 return die_("copying metadata");
1665 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1666 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1668 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1671 printf("SV[P]PPA\tnext\n");
1672 if(!FLAC__metadata_iterator_next(iterator))
1673 return die_("iterator ended early\n");
1674 our_current_position++;
1676 printf("SVP[P]PA\tnext\n");
1677 if(!FLAC__metadata_iterator_next(iterator))
1678 return die_("iterator ended early\n");
1679 our_current_position++;
1681 printf("SVPP[P]A\tnext\n");
1682 if(!FLAC__metadata_iterator_next(iterator))
1683 return die_("iterator ended early\n");
1684 our_current_position++;
1686 printf("SVPPP[A]\tinsert PADDING after\n");
1687 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1688 return die_("creating PADDING block");
1689 padding->length = 57;
1690 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1691 return die_("copying metadata");
1692 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1693 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1695 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1698 printf("SVPPPA[P]\tinsert PADDING before\n");
1699 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1700 return die_("creating PADDING block");
1701 padding->length = 99;
1702 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1703 return die_("copying metadata");
1704 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1705 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1707 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1710 printf("delete iterator\n");
1711 FLAC__metadata_iterator_delete(iterator);
1712 our_current_position = 0;
1714 printf("SVPPPAPP\tmerge padding\n");
1715 FLAC__metadata_chain_merge_padding(chain);
1716 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1717 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1718 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1719 delete_from_our_metadata_(7);
1720 delete_from_our_metadata_(4);
1721 delete_from_our_metadata_(3);
1723 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1724 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1725 if(!compare_chain_(chain, 0, 0))
1727 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1730 printf("SVPAP\tsort padding\n");
1731 FLAC__metadata_chain_sort_padding(chain);
1732 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1733 delete_from_our_metadata_(2);
1735 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1736 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1737 if(!compare_chain_(chain, 0, 0))
1739 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1742 printf("create iterator\n");
1743 if(0 == (iterator = FLAC__metadata_iterator_new()))
1744 return die_("allocating memory for iterator");
1746 our_current_position = 0;
1748 FLAC__metadata_iterator_init(iterator, chain);
1750 printf("[S]VAP\tnext\n");
1751 if(!FLAC__metadata_iterator_next(iterator))
1752 return die_("iterator ended early\n");
1753 our_current_position++;
1755 printf("S[V]AP\tnext\n");
1756 if(!FLAC__metadata_iterator_next(iterator))
1757 return die_("iterator ended early\n");
1758 our_current_position++;
1760 printf("SV[A]P\tdelete middle block, replace with padding\n");
1761 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1762 return die_("creating PADDING block");
1763 padding->length = 71;
1764 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1765 return die_("copying object");
1766 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1767 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1769 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1772 printf("S[V]PP\tnext\n");
1773 if(!FLAC__metadata_iterator_next(iterator))
1774 return die_("iterator ended early\n");
1775 our_current_position++;
1777 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1778 delete_from_our_metadata_(our_current_position--);
1779 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1780 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1782 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1785 printf("S[V]P\tnext\n");
1786 if(!FLAC__metadata_iterator_next(iterator))
1787 return die_("iterator ended early\n");
1788 our_current_position++;
1790 printf("SV[P]\tdelete last block, replace with padding\n");
1791 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1792 return die_("creating PADDING block");
1793 padding->length = 219;
1794 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1795 return die_("copying object");
1796 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1797 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1799 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1802 printf("S[V]P\tnext\n");
1803 if(!FLAC__metadata_iterator_next(iterator))
1804 return die_("iterator ended early\n");
1805 our_current_position++;
1807 printf("SV[P]\tdelete last block, don't replace with padding\n");
1808 delete_from_our_metadata_(our_current_position--);
1809 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1810 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1812 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1815 printf("S[V]\tprev\n");
1816 if(!FLAC__metadata_iterator_prev(iterator))
1817 return die_("iterator ended early\n");
1818 our_current_position--;
1820 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1821 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1822 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1824 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1827 printf("delete iterator\n");
1828 FLAC__metadata_iterator_delete(iterator);
1829 our_current_position = 0;
1831 printf("SV\tmerge padding\n");
1832 FLAC__metadata_chain_merge_padding(chain);
1834 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1835 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1836 if(!compare_chain_(chain, 0, 0))
1838 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1841 printf("SV\tsort padding\n");
1842 FLAC__metadata_chain_sort_padding(chain);
1844 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1845 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1846 if(!compare_chain_(chain, 0, 0))
1848 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1851 printf("delete chain\n");
1853 FLAC__metadata_chain_delete(chain);
1855 if(!remove_file_(flacfile_))
1861 static FLAC__bool test_level_2_misc_()
1863 FLAC__Metadata_Iterator *iterator;
1864 FLAC__Metadata_Chain *chain;
1865 FLAC__IOCallbacks callbacks;
1867 memset(&callbacks, 0, sizeof(callbacks));
1868 callbacks.read = (FLAC__IOCallback_Read)fread;
1869 #ifdef FLAC__VALGRIND_TESTING
1870 callbacks.write = chain_write_cb_;
1872 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1874 callbacks.seek = chain_seek_cb_;
1875 callbacks.tell = chain_tell_cb_;
1876 callbacks.eof = chain_eof_cb_;
1878 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1880 printf("generate file\n");
1882 if(!generate_file_(/*include_cuesheet=*/false))
1885 printf("create chain\n");
1887 if(0 == (chain = FLAC__metadata_chain_new()))
1888 return die_("allocating chain");
1890 printf("read chain (filename-based)\n");
1892 if(!FLAC__metadata_chain_read(chain, flacfile_))
1893 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1895 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1897 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1898 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1899 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1900 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1901 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1904 printf("read chain (filename-based)\n");
1906 if(!FLAC__metadata_chain_read(chain, flacfile_))
1907 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1909 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1911 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1912 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1913 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1914 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1915 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1918 printf("read chain (callback-based)\n");
1920 FILE *file = fopen(flacfile_, "rb");
1922 return die_("opening file");
1923 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1925 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1930 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1932 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1933 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1934 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1935 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1936 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1939 printf("read chain (callback-based)\n");
1941 FILE *file = fopen(flacfile_, "rb");
1943 return die_("opening file");
1944 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1946 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1951 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1953 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1954 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1956 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1958 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1960 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1961 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1962 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1963 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1964 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1967 printf("read chain (callback-based)\n");
1969 FILE *file = fopen(flacfile_, "rb");
1971 return die_("opening file");
1972 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1974 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1979 printf("create iterator\n");
1980 if(0 == (iterator = FLAC__metadata_iterator_new()))
1981 return die_("allocating memory for iterator");
1983 FLAC__metadata_iterator_init(iterator, chain);
1985 printf("[S]VP\tnext\n");
1986 if(!FLAC__metadata_iterator_next(iterator))
1987 return die_("iterator ended early\n");
1989 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1990 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1991 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1993 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1995 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1996 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1998 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2000 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2002 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2003 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2004 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2005 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2006 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2009 printf("delete iterator\n");
2011 FLAC__metadata_iterator_delete(iterator);
2013 printf("delete chain\n");
2015 FLAC__metadata_chain_delete(chain);
2017 if(!remove_file_(flacfile_))
2023 FLAC__bool test_metadata_file_manipulation()
2025 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2027 our_metadata_.num_blocks = 0;
2029 if(!test_level_0_())
2032 if(!test_level_1_())
2035 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2037 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2039 if(!test_level_2_misc_())