1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002,2003,2004 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include "file_utils.h"
20 #include "metadata_utils.h"
21 #include "FLAC/assert.h"
22 #include "FLAC/file_decoder.h"
23 #include "FLAC/metadata.h"
24 #include "share/grabbag.h"
26 #include <stdlib.h> /* for malloc() */
28 #if defined _MSC_VER || defined __MINGW32__
29 #include <sys/utime.h> /* for utime() */
30 #include <io.h> /* for chmod() */
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() */
39 /******************************************************************************
40 The general strategy of these tests (for interface levels 1 and 2) is
41 to create a dummy FLAC file with a known set of initial metadata
42 blocks, then keep a mirror locally of what we expect the metadata to be
43 after each operation. Then testing becomes a simple matter of running
44 a FLAC__FileDecoder over the dummy file after each operation, comparing
45 the decoded metadata to what's in our local copy. If there are any
46 differences in the metadata, or the actual audio data is corrupted, we
47 will catch it while decoding.
48 ******************************************************************************/
51 FLAC__bool error_occurred;
52 } decoder_client_struct;
55 FLAC__StreamMetadata *blocks[64];
57 } our_metadata_struct;
59 static const char *flacfile_ = "metadata.flac";
61 /* our copy of the metadata in flacfile_ */
62 static our_metadata_struct our_metadata_;
64 /* the current block number that corresponds to the position of the iterator we are testing */
65 static unsigned mc_our_block_number_ = 0;
67 static FLAC__bool die_(const char *msg)
69 printf("ERROR: %s\n", msg);
73 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
75 printf("ERROR: %s\n", msg);
76 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
80 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
82 printf("ERROR: %s\n", msg);
83 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
87 static void *malloc_or_die_(size_t size)
89 void *x = malloc(size);
91 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
97 /* functions for working with our metadata copy */
99 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
102 FLAC__StreamMetadata *obj = block;
103 FLAC__ASSERT(position < our_metadata_.num_blocks);
105 if(0 == (obj = FLAC__metadata_object_clone(block)))
106 return die_("during FLAC__metadata_object_clone()");
108 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
109 our_metadata_.blocks[position] = obj;
111 /* set the is_last flags */
112 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
113 our_metadata_.blocks[i]->is_last = false;
114 our_metadata_.blocks[i]->is_last = true;
119 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
122 FLAC__StreamMetadata *obj = block;
124 if(0 == (obj = FLAC__metadata_object_clone(block)))
125 return die_("during FLAC__metadata_object_clone()");
127 if(position > our_metadata_.num_blocks) {
128 position = our_metadata_.num_blocks;
131 for(i = our_metadata_.num_blocks; i > position; i--)
132 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
134 our_metadata_.blocks[position] = obj;
135 our_metadata_.num_blocks++;
137 /* set the is_last flags */
138 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
139 our_metadata_.blocks[i]->is_last = false;
140 our_metadata_.blocks[i]->is_last = true;
145 static void delete_from_our_metadata_(unsigned position)
148 FLAC__ASSERT(position < our_metadata_.num_blocks);
149 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
150 for(i = position; i < our_metadata_.num_blocks - 1; i++)
151 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
152 our_metadata_.num_blocks--;
154 /* set the is_last flags */
155 if(our_metadata_.num_blocks > 0) {
156 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
157 our_metadata_.blocks[i]->is_last = false;
158 our_metadata_.blocks[i]->is_last = true;
163 * This wad of functions supports filename- and callback-based chain reading/writing.
164 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
166 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
168 static const char *tempfile_suffix = ".metadata_edit";
170 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
172 strcpy(*tempfilename, filename);
173 strcat(*tempfilename, tempfile_suffix);
175 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
181 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
184 (void)fclose(*tempfile);
188 if(0 != *tempfilename) {
189 (void)unlink(*tempfilename);
195 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
197 FLAC__ASSERT(0 != filename);
198 FLAC__ASSERT(0 != tempfile);
199 FLAC__ASSERT(0 != tempfilename);
200 FLAC__ASSERT(0 != *tempfilename);
203 (void)fclose(*tempfile);
207 #if defined _MSC_VER || defined __MINGW32__
208 if(unlink(filename) < 0) {
209 cleanup_tempfile_(tempfile, tempfilename);
214 if(0 != rename(*tempfilename, filename)) {
215 cleanup_tempfile_(tempfile, tempfilename);
219 cleanup_tempfile_(tempfile, tempfilename);
224 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
226 FLAC__ASSERT(0 != filename);
227 FLAC__ASSERT(0 != stats);
228 return (0 == stat(filename, stats));
231 void set_file_stats_(const char *filename, struct stat *stats)
233 struct utimbuf srctime;
235 FLAC__ASSERT(0 != filename);
236 FLAC__ASSERT(0 != stats);
238 srctime.actime = stats->st_atime;
239 srctime.modtime = stats->st_mtime;
240 (void)chmod(filename, stats->st_mode);
241 (void)utime(filename, &srctime);
242 #if !defined _MSC_VER && !defined __MINGW32__
243 (void)chown(filename, stats->st_uid, -1);
244 (void)chown(filename, -1, stats->st_gid);
248 #ifdef FLAC__VALGRIND_TESTING
249 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
251 FILE *stream = (FILE*)handle;
252 size_t ret = fwrite(ptr, size, nmemb, stream);
259 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
261 long o = (long)offset;
262 FLAC__ASSERT(offset == o);
263 return fseek((FILE*)handle, o, whence);
266 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
268 return ftell((FILE*)handle);
271 static int chain_eof_cb_(FLAC__IOHandle handle)
273 return feof((FILE*)handle);
276 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)
279 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
281 FLAC__IOCallbacks callbacks;
283 memset(&callbacks, 0, sizeof(callbacks));
284 callbacks.read = (FLAC__IOCallback_Read)fread;
285 #ifdef FLAC__VALGRIND_TESTING
286 callbacks.write = chain_write_cb_;
288 callbacks.write = (FLAC__IOCallback_Write)fwrite;
290 callbacks.seek = chain_seek_cb_;
291 callbacks.eof = chain_eof_cb_;
293 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
295 FILE *file, *tempfile;
297 if(preserve_file_stats) {
298 if(!get_file_stats_(filename, &stats))
301 if(0 == (file = fopen(filename, "rb")))
302 return false; /*@@@ chain status still says OK though */
303 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
305 cleanup_tempfile_(&tempfile, &tempfilename);
306 return false; /*@@@ chain status still says OK though */
308 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
316 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
318 if(preserve_file_stats)
319 set_file_stats_(filename, &stats);
322 FILE *file = fopen(filename, "r+b");
324 return false; /*@@@ chain status still says OK though */
325 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
334 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
337 return FLAC__metadata_chain_read(chain, flacfile_);
339 FLAC__IOCallbacks callbacks;
341 memset(&callbacks, 0, sizeof(callbacks));
342 callbacks.read = (FLAC__IOCallback_Read)fread;
343 callbacks.seek = chain_seek_cb_;
344 callbacks.tell = chain_tell_cb_;
348 FILE *file = fopen(filename, "rb");
350 return false; /*@@@ chain status still says OK though */
351 ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
358 /* function for comparing our metadata to a FLAC__Metadata_Chain */
360 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
363 FLAC__Metadata_Iterator *iterator;
364 FLAC__StreamMetadata *block;
365 FLAC__bool next_ok = true;
367 FLAC__ASSERT(0 != chain);
369 printf("\tcomparing chain... ");
372 if(0 == (iterator = FLAC__metadata_iterator_new()))
373 return die_("allocating memory for iterator");
375 FLAC__metadata_iterator_init(iterator, chain);
382 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
383 FLAC__metadata_iterator_delete(iterator);
384 return die_("getting block from iterator");
387 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
388 FLAC__metadata_iterator_delete(iterator);
389 return die_("metadata block mismatch");
393 next_ok = FLAC__metadata_iterator_next(iterator);
394 } while(i < our_metadata_.num_blocks && next_ok);
396 FLAC__metadata_iterator_delete(iterator);
399 return die_("chain has more blocks than expected");
401 if(i < our_metadata_.num_blocks)
402 return die_("short block count in chain");
404 if(0 != current_block) {
405 printf("CURRENT_POSITION... ");
408 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
409 return die_("metadata block mismatch");
417 /* decoder callbacks for checking the file */
419 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
421 (void)decoder, (void)buffer, (void)client_data;
424 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
425 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
427 printf("content... ");
431 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
434 /* this version pays no attention to the metadata */
435 static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
437 (void)decoder, (void)metadata, (void)client_data;
439 printf("%d... ", mc_our_block_number_);
442 mc_our_block_number_++;
445 /* this version is used when we want to compare to our metadata copy */
446 static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
448 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
452 /* don't bother checking if we've already hit an error */
453 if(dcd->error_occurred)
456 printf("%d... ", mc_our_block_number_);
459 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
460 (void)die_("got more metadata blocks than expected");
461 dcd->error_occurred = true;
464 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
465 (void)die_("metadata block mismatch");
466 dcd->error_occurred = true;
469 mc_our_block_number_++;
472 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
474 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
477 dcd->error_occurred = true;
478 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
481 static FLAC__bool generate_file_()
483 FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
484 FLAC__StreamMetadata *metadata[1];
486 printf("generating FLAC file for test\n");
488 while(our_metadata_.num_blocks > 0)
489 delete_from_our_metadata_(0);
491 streaminfo.is_last = false;
492 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
493 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
494 streaminfo.data.stream_info.min_blocksize = 576;
495 streaminfo.data.stream_info.max_blocksize = 576;
496 streaminfo.data.stream_info.min_framesize = 0;
497 streaminfo.data.stream_info.max_framesize = 0;
498 streaminfo.data.stream_info.sample_rate = 44100;
499 streaminfo.data.stream_info.channels = 1;
500 streaminfo.data.stream_info.bits_per_sample = 8;
501 streaminfo.data.stream_info.total_samples = 0;
502 memset(streaminfo.data.stream_info.md5sum, 0, 16);
505 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
506 vorbiscomment.is_last = false;
507 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
508 vorbiscomment.length = (4 + vendor_string_length) + 4;
509 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
510 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
511 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
512 vorbiscomment.data.vorbis_comment.num_comments = 0;
513 vorbiscomment.data.vorbis_comment.comments = 0;
516 padding.is_last = true;
517 padding.type = FLAC__METADATA_TYPE_PADDING;
518 padding.length = 1234;
520 metadata[0] = &padding;
523 !insert_to_our_metadata_(&streaminfo, 0, /*copy=*/true) ||
524 !insert_to_our_metadata_(&vorbiscomment, 1, /*copy=*/true) ||
525 !insert_to_our_metadata_(&padding, 2, /*copy=*/true)
527 return die_("priming our metadata");
529 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
530 return die_("creating the encoded file");
532 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
537 static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
539 FLAC__FileDecoder *decoder;
540 decoder_client_struct decoder_client_data;
542 FLAC__ASSERT(0 != filename);
543 FLAC__ASSERT(0 != metadata_callback);
545 mc_our_block_number_ = 0;
546 decoder_client_data.error_occurred = false;
548 printf("\ttesting '%s'... ", filename);
551 if(0 == (decoder = FLAC__file_decoder_new()))
552 return die_("couldn't allocate decoder instance");
554 FLAC__file_decoder_set_md5_checking(decoder, true);
555 FLAC__file_decoder_set_filename(decoder, filename);
556 FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
557 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
558 FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
559 FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
560 FLAC__file_decoder_set_metadata_respond_all(decoder);
561 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
562 FLAC__file_decoder_finish(decoder);
563 FLAC__file_decoder_delete(decoder);
564 return die_("initializing decoder\n");
566 if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
567 FLAC__file_decoder_finish(decoder);
568 FLAC__file_decoder_delete(decoder);
569 return die_("decoding file\n");
572 FLAC__file_decoder_finish(decoder);
573 FLAC__file_decoder_delete(decoder);
575 if(decoder_client_data.error_occurred)
578 if(mc_our_block_number_ != our_metadata_.num_blocks)
579 return die_("short metadata block count");
585 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
587 if(!grabbag__file_change_stats(filename, read_only))
588 return die_("during grabbag__file_change_stats()");
593 static FLAC__bool remove_file_(const char *filename)
595 while(our_metadata_.num_blocks > 0)
596 delete_from_our_metadata_(0);
598 if(!grabbag__file_remove_file(filename))
599 return die_("removing file");
604 static FLAC__bool test_level_0_()
606 FLAC__StreamMetadata streaminfo;
607 FLAC__StreamMetadata *tags = 0;
609 printf("\n\n++++++ testing level 0 interface\n");
611 if(!generate_file_())
614 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
617 printf("testing FLAC__metadata_get_streaminfo()... ");
619 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
620 return die_("during FLAC__metadata_get_streaminfo()");
622 /* check to see if some basic data matches (c.f. generate_file_()) */
623 if(streaminfo.data.stream_info.channels != 1)
624 return die_("mismatch in streaminfo.data.stream_info.channels");
625 if(streaminfo.data.stream_info.bits_per_sample != 8)
626 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
627 if(streaminfo.data.stream_info.sample_rate != 44100)
628 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
629 if(streaminfo.data.stream_info.min_blocksize != 576)
630 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
631 if(streaminfo.data.stream_info.max_blocksize != 576)
632 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
636 printf("testing FLAC__metadata_get_tags()... ");
638 if(!FLAC__metadata_get_tags(flacfile_, &tags))
639 return die_("during FLAC__metadata_get_tags()");
641 /* check to see if some basic data matches (c.f. generate_file_()) */
642 if(tags->data.vorbis_comment.num_comments != 0)
643 return die_("mismatch in tags->data.vorbis_comment.num_comments");
647 FLAC__metadata_object_delete(tags);
649 if(!remove_file_(flacfile_))
655 static FLAC__bool test_level_1_()
657 FLAC__Metadata_SimpleIterator *iterator;
658 FLAC__StreamMetadata *block, *app, *padding;
659 FLAC__byte data[1000];
660 unsigned our_current_position = 0;
662 /* initialize 'data' to avoid Valgrind errors */
663 memset(data, 0, sizeof(data));
665 printf("\n\n++++++ testing level 1 interface\n");
667 /************************************************************/
669 printf("simple iterator on read-only file\n");
671 if(!generate_file_())
674 if(!change_stats_(flacfile_, /*read_only=*/true))
677 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
680 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
681 return die_("FLAC__metadata_simple_iterator_new()");
683 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
684 return die_("FLAC__metadata_simple_iterator_init() returned false");
686 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
687 if(FLAC__metadata_simple_iterator_is_writable(iterator))
688 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
690 printf("iterate forwards\n");
692 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
693 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
694 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
695 return die_("getting block 0");
696 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
697 return die_("expected STREAMINFO type");
699 return die_("expected is_last to be false");
700 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
701 return die_("bad STREAMINFO length");
702 /* check to see if some basic data matches (c.f. generate_file_()) */
703 if(block->data.stream_info.channels != 1)
704 return die_("mismatch in channels");
705 if(block->data.stream_info.bits_per_sample != 8)
706 return die_("mismatch in bits_per_sample");
707 if(block->data.stream_info.sample_rate != 44100)
708 return die_("mismatch in sample_rate");
709 if(block->data.stream_info.min_blocksize != 576)
710 return die_("mismatch in min_blocksize");
711 if(block->data.stream_info.max_blocksize != 576)
712 return die_("mismatch in max_blocksize");
713 FLAC__metadata_object_delete(block);
715 if(!FLAC__metadata_simple_iterator_next(iterator))
716 return die_("forward iterator ended early");
717 our_current_position++;
719 if(!FLAC__metadata_simple_iterator_next(iterator))
720 return die_("forward iterator ended early");
721 our_current_position++;
723 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
724 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
725 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
726 return die_("getting block 2");
727 if(block->type != FLAC__METADATA_TYPE_PADDING)
728 return die_("expected PADDING type");
730 return die_("expected is_last to be true");
731 /* check to see if some basic data matches (c.f. generate_file_()) */
732 if(block->length != 1234)
733 return die_("bad PADDING length");
734 FLAC__metadata_object_delete(block);
736 if(FLAC__metadata_simple_iterator_next(iterator))
737 return die_("forward iterator returned true but should have returned false");
739 printf("iterate backwards\n");
740 if(!FLAC__metadata_simple_iterator_prev(iterator))
741 return die_("reverse iterator ended early");
742 if(!FLAC__metadata_simple_iterator_prev(iterator))
743 return die_("reverse iterator ended early");
744 if(FLAC__metadata_simple_iterator_prev(iterator))
745 return die_("reverse iterator returned true but should have returned false");
747 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
749 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
750 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
752 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
754 FLAC__metadata_simple_iterator_delete(iterator);
756 /************************************************************/
758 printf("simple iterator on writable file\n");
760 if(!change_stats_(flacfile_, /*read-only=*/false))
763 printf("creating APPLICATION block\n");
765 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
766 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
767 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
769 printf("creating PADDING block\n");
771 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
772 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
773 padding->length = 20;
775 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
776 return die_("FLAC__metadata_simple_iterator_new()");
778 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
779 return die_("FLAC__metadata_simple_iterator_init() returned false");
780 our_current_position = 0;
782 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
784 printf("[S]VP\ttry to write over STREAMINFO block...\n");
785 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
786 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
788 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
790 printf("[S]VP\tnext\n");
791 if(!FLAC__metadata_simple_iterator_next(iterator))
792 return die_("iterator ended early\n");
793 our_current_position++;
795 printf("S[V]P\tnext\n");
796 if(!FLAC__metadata_simple_iterator_next(iterator))
797 return die_("iterator ended early\n");
798 our_current_position++;
800 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
801 padding->length = 25;
802 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
803 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
804 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
807 printf("SVP[P]\tprev\n");
808 if(!FLAC__metadata_simple_iterator_prev(iterator))
809 return die_("iterator ended early\n");
810 our_current_position--;
812 printf("SV[P]P\tprev\n");
813 if(!FLAC__metadata_simple_iterator_prev(iterator))
814 return die_("iterator ended early\n");
815 our_current_position--;
817 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
818 padding->length = 30;
819 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
820 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
821 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
824 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
827 printf("SV[P]PP\tprev\n");
828 if(!FLAC__metadata_simple_iterator_prev(iterator))
829 return die_("iterator ended early\n");
830 our_current_position--;
832 printf("S[V]PPP\tprev\n");
833 if(!FLAC__metadata_simple_iterator_prev(iterator))
834 return die_("iterator ended early\n");
835 our_current_position--;
837 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
838 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
839 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
841 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
844 printf("[S]VPPP\tnext\n");
845 if(!FLAC__metadata_simple_iterator_next(iterator))
846 return die_("iterator ended early\n");
847 our_current_position++;
849 printf("S[V]PPP\tnext\n");
850 if(!FLAC__metadata_simple_iterator_next(iterator))
851 return die_("iterator ended early\n");
852 our_current_position++;
854 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
855 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
856 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
857 our_current_position--;
859 printf("S[V]PPP\tnext\n");
860 if(!FLAC__metadata_simple_iterator_next(iterator))
861 return die_("iterator ended early\n");
862 our_current_position++;
864 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
865 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
866 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
867 delete_from_our_metadata_(our_current_position--);
869 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
872 printf("S[V]PP\tnext\n");
873 if(!FLAC__metadata_simple_iterator_next(iterator))
874 return die_("iterator ended early\n");
875 our_current_position++;
877 printf("SV[P]P\tnext\n");
878 if(!FLAC__metadata_simple_iterator_next(iterator))
879 return die_("iterator ended early\n");
880 our_current_position++;
882 printf("SVP[P]\tdelete (last block), replace with padding\n");
883 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
884 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
885 our_current_position--;
887 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
890 printf("SV[P]P\tnext\n");
891 if(!FLAC__metadata_simple_iterator_next(iterator))
892 return die_("iterator ended early\n");
893 our_current_position++;
895 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
896 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
897 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
898 delete_from_our_metadata_(our_current_position--);
900 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
903 printf("SV[P]\tprev\n");
904 if(!FLAC__metadata_simple_iterator_prev(iterator))
905 return die_("iterator ended early\n");
906 our_current_position--;
908 printf("S[V]P\tprev\n");
909 if(!FLAC__metadata_simple_iterator_prev(iterator))
910 return die_("iterator ended early\n");
911 our_current_position--;
913 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
914 FLAC__ASSERT(our_current_position == 0);
915 block = FLAC__metadata_simple_iterator_get_block(iterator);
916 block->data.stream_info.sample_rate = 32000;
917 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
918 return die_("copying object");
919 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
920 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
921 FLAC__metadata_object_delete(block);
923 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
926 printf("[S]VP\tnext\n");
927 if(!FLAC__metadata_simple_iterator_next(iterator))
928 return die_("iterator ended early\n");
929 our_current_position++;
931 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
932 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
933 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
934 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
935 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
937 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
939 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
942 printf("SV[A]P\tnext\n");
943 if(!FLAC__metadata_simple_iterator_next(iterator))
944 return die_("iterator ended early\n");
945 our_current_position++;
947 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
948 app->data.application.id[0] = 'f'; /* twiddle the id */
949 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
950 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
951 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
953 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
955 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
958 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
959 app->data.application.id[0] = 'g'; /* twiddle the id */
960 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
961 return die_("setting APPLICATION data");
962 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
963 return die_("copying object");
964 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
965 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
967 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
970 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
971 app->data.application.id[0] = 'h'; /* twiddle the id */
972 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
973 return die_("setting APPLICATION data");
974 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
975 return die_("copying object");
976 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
977 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
979 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
982 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
983 app->data.application.id[0] = 'i'; /* twiddle the id */
984 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
985 return die_("setting APPLICATION data");
986 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
987 return die_("copying object");
988 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
989 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
990 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
992 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
995 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
996 app->data.application.id[0] = 'j'; /* twiddle the id */
997 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
998 return die_("setting APPLICATION data");
999 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1000 return die_("copying object");
1001 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1002 return die_("copying object");
1003 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1004 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1005 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1007 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1010 printf("SVA[A]PP\tnext\n");
1011 if(!FLAC__metadata_simple_iterator_next(iterator))
1012 return die_("iterator ended early\n");
1013 our_current_position++;
1015 printf("SVAA[P]P\tnext\n");
1016 if(!FLAC__metadata_simple_iterator_next(iterator))
1017 return die_("iterator ended early\n");
1018 our_current_position++;
1020 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1021 padding->length = 5;
1022 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1023 return die_("copying object");
1024 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1025 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1027 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1030 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1031 app->data.application.id[0] = 'k'; /* twiddle the id */
1032 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1033 return die_("copying object");
1034 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1035 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1037 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1040 printf("SVAAP[A]\tset PADDING (equal)\n");
1041 padding->length = 27;
1042 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1043 return die_("copying object");
1044 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1045 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1047 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1050 printf("SVAAP[P]\tprev\n");
1051 if(!FLAC__metadata_simple_iterator_prev(iterator))
1052 return die_("iterator ended early\n");
1053 our_current_position--;
1055 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1056 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1057 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1058 delete_from_our_metadata_(our_current_position--);
1060 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1063 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1064 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1065 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1066 delete_from_our_metadata_(our_current_position--);
1068 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1071 printf("SV[A]P\tnext\n");
1072 if(!FLAC__metadata_simple_iterator_next(iterator))
1073 return die_("iterator ended early\n");
1074 our_current_position++;
1076 printf("SVA[P]\tinsert PADDING after\n");
1077 padding->length = 5;
1078 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1079 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1080 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1083 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1086 printf("SVAP[P]\tprev\n");
1087 if(!FLAC__metadata_simple_iterator_prev(iterator))
1088 return die_("iterator ended early\n");
1089 our_current_position--;
1091 printf("SVA[P]P\tprev\n");
1092 if(!FLAC__metadata_simple_iterator_prev(iterator))
1093 return die_("iterator ended early\n");
1094 our_current_position--;
1096 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1097 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1098 return die_("setting APPLICATION data");
1099 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1100 return die_("copying object");
1101 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1102 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1104 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1107 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1108 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1109 return die_("setting APPLICATION data");
1110 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1111 return die_("copying object");
1112 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1113 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1115 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1118 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1119 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1120 return die_("setting APPLICATION data");
1121 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1122 return die_("copying object");
1123 our_metadata_.blocks[our_current_position+1]->length = 0;
1124 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1125 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1127 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1130 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1131 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1132 return die_("setting APPLICATION data");
1133 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1134 return die_("copying object");
1135 delete_from_our_metadata_(our_current_position+1);
1136 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1137 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1139 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1142 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1143 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1144 return die_("setting APPLICATION data");
1145 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1146 return die_("copying object");
1147 delete_from_our_metadata_(our_current_position+1);
1148 our_metadata_.blocks[our_current_position]->is_last = true;
1149 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1150 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1152 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1155 printf("SV[A]\tset PADDING (equal size)\n");
1156 padding->length = app->length;
1157 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1158 return die_("copying object");
1159 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1160 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1162 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1165 printf("SV[P]\tinsert PADDING after\n");
1166 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1167 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1168 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1171 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1174 printf("SVP[P]\tinsert PADDING after\n");
1175 padding->length = 5;
1176 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1177 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1178 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1181 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1184 printf("SVPP[P]\tprev\n");
1185 if(!FLAC__metadata_simple_iterator_prev(iterator))
1186 return die_("iterator ended early\n");
1187 our_current_position--;
1189 printf("SVP[P]P\tprev\n");
1190 if(!FLAC__metadata_simple_iterator_prev(iterator))
1191 return die_("iterator ended early\n");
1192 our_current_position--;
1194 printf("SV[P]PP\tprev\n");
1195 if(!FLAC__metadata_simple_iterator_prev(iterator))
1196 return die_("iterator ended early\n");
1197 our_current_position--;
1199 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1200 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1201 return die_("setting APPLICATION data");
1202 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1203 return die_("copying object");
1204 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1205 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1207 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1210 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1211 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1212 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1213 delete_from_our_metadata_(our_current_position--);
1215 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1218 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1219 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1220 return die_("setting APPLICATION data");
1221 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1222 return die_("copying object");
1223 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1224 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1226 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1229 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1230 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1231 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1232 delete_from_our_metadata_(our_current_position--);
1234 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1237 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1238 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1239 return die_("setting APPLICATION data");
1240 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1241 return die_("copying object");
1242 delete_from_our_metadata_(our_current_position+1);
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]PP\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]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1258 if(!FLAC__metadata_object_application_set_data(app, data, 96, 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 our_metadata_.blocks[our_current_position+1]->length = 0;
1263 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1264 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1266 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1269 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1270 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1271 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1272 delete_from_our_metadata_(our_current_position--);
1274 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1277 printf("S[V]PP\tnext\n");
1278 if(!FLAC__metadata_simple_iterator_next(iterator))
1279 return die_("iterator ended early\n");
1280 our_current_position++;
1282 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1283 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1284 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1285 delete_from_our_metadata_(our_current_position--);
1287 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1290 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1291 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1292 return die_("setting APPLICATION data");
1293 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1294 return die_("copying object");
1295 delete_from_our_metadata_(our_current_position+1);
1296 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1297 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1299 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1302 printf("delete simple iterator\n");
1304 FLAC__metadata_simple_iterator_delete(iterator);
1306 FLAC__metadata_object_delete(app);
1307 FLAC__metadata_object_delete(padding);
1309 if(!remove_file_(flacfile_))
1315 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1317 FLAC__Metadata_Iterator *iterator;
1318 FLAC__Metadata_Chain *chain;
1319 FLAC__StreamMetadata *block, *app, *padding;
1320 FLAC__byte data[2000];
1321 unsigned our_current_position;
1323 /* initialize 'data' to avoid Valgrind errors */
1324 memset(data, 0, sizeof(data));
1326 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1328 printf("generate read-only file\n");
1330 if(!generate_file_())
1333 if(!change_stats_(flacfile_, /*read_only=*/true))
1336 printf("create chain\n");
1338 if(0 == (chain = FLAC__metadata_chain_new()))
1339 return die_("allocating chain");
1341 printf("read chain\n");
1343 if(!read_chain_(chain, flacfile_, filename_based))
1344 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1346 printf("[S]VP\ttest initial metadata\n");
1348 if(!compare_chain_(chain, 0, 0))
1350 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1353 printf("switch file to read-write\n");
1355 if(!change_stats_(flacfile_, /*read-only=*/false))
1358 printf("create iterator\n");
1359 if(0 == (iterator = FLAC__metadata_iterator_new()))
1360 return die_("allocating memory for iterator");
1362 our_current_position = 0;
1364 FLAC__metadata_iterator_init(iterator, chain);
1366 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1367 return die_("getting block from iterator");
1369 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1371 printf("[S]VP\tmodify STREAMINFO, write\n");
1373 block->data.stream_info.sample_rate = 32000;
1374 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1375 return die_("copying object");
1377 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1378 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1379 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1381 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1384 printf("[S]VP\tnext\n");
1385 if(!FLAC__metadata_iterator_next(iterator))
1386 return die_("iterator ended early\n");
1387 our_current_position++;
1389 printf("S[V]P\tnext\n");
1390 if(!FLAC__metadata_iterator_next(iterator))
1391 return die_("iterator ended early\n");
1392 our_current_position++;
1394 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1395 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1396 return die_("getting block from iterator");
1397 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1398 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1399 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1400 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1401 return die_("setting APPLICATION data");
1402 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1403 return die_("copying object");
1404 if(!FLAC__metadata_iterator_set_block(iterator, app))
1405 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1407 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1408 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1409 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1411 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1414 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1415 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1416 return die_("copying object");
1417 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1418 return die_("setting APPLICATION data");
1419 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1420 return die_("copying object");
1421 if(!FLAC__metadata_iterator_set_block(iterator, app))
1422 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1424 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1425 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1426 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1428 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1431 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1432 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1433 return die_("copying object");
1434 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1435 return die_("setting APPLICATION data");
1436 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1437 return die_("copying object");
1438 if(!FLAC__metadata_iterator_set_block(iterator, app))
1439 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1441 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1442 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1443 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1445 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1448 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1449 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1450 return die_("copying object");
1451 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1452 return die_("setting APPLICATION data");
1453 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1454 return die_("copying object");
1455 if(!FLAC__metadata_iterator_set_block(iterator, app))
1456 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1458 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1459 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1460 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1462 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1465 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1466 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1467 return die_("copying object");
1468 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1469 return die_("setting APPLICATION data");
1470 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1471 return die_("copying object");
1472 if(!FLAC__metadata_iterator_set_block(iterator, app))
1473 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1475 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1476 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1477 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1479 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1482 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1483 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1484 return die_("creating PADDING block");
1485 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1486 return die_("copying object");
1487 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1488 return die_("setting APPLICATION data");
1489 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1490 return die_("copying object");
1491 padding->length = 0;
1492 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1493 return die_("internal error");
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=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1498 return die_c_("during FLAC__metadata_chain_write(chain, true, 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]P\tshrink APPLICATION, use padding, last block is padding\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, 16, 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 our_metadata_.blocks[our_current_position+1]->length = 13;
1512 if(!FLAC__metadata_iterator_set_block(iterator, app))
1513 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1515 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1516 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1517 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1519 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1522 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1523 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1524 return die_("copying object");
1525 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1526 return die_("setting APPLICATION data");
1527 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1528 return die_("copying object");
1529 if(!FLAC__metadata_iterator_set_block(iterator, app))
1530 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1532 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1533 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1534 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1536 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1539 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1540 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1541 return die_("copying object");
1542 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1543 return die_("setting APPLICATION data");
1544 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1545 return die_("copying object");
1546 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1547 if(!FLAC__metadata_iterator_set_block(iterator, app))
1548 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1550 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1551 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1552 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1554 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1557 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1558 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1559 return die_("copying object");
1560 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1561 return die_("setting APPLICATION data");
1562 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1563 return die_("copying object");
1564 delete_from_our_metadata_(our_current_position+1);
1565 if(!FLAC__metadata_iterator_set_block(iterator, app))
1566 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1568 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1569 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1570 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1572 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1575 printf("SV[A]\tprev\n");
1576 if(!FLAC__metadata_iterator_prev(iterator))
1577 return die_("iterator ended early\n");
1578 our_current_position--;
1580 printf("S[V]A\tprev\n");
1581 if(!FLAC__metadata_iterator_prev(iterator))
1582 return die_("iterator ended early\n");
1583 our_current_position--;
1585 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1586 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1587 return die_("creating PADDING block");
1588 padding->length = 30;
1589 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1590 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1592 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1594 printf("[S]VP\tnext\n");
1595 if(!FLAC__metadata_iterator_next(iterator))
1596 return die_("iterator ended early\n");
1597 our_current_position++;
1599 printf("S[V]A\tinsert PADDING after\n");
1600 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1601 return die_("copying metadata");
1602 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1603 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1605 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1608 printf("SV[P]A\tinsert PADDING before\n");
1609 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1610 return die_("creating PADDING block");
1611 padding->length = 17;
1612 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1613 return die_("copying metadata");
1614 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1615 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1617 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1620 printf("SV[P]PA\tinsert PADDING before\n");
1621 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1622 return die_("creating PADDING block");
1623 padding->length = 0;
1624 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1625 return die_("copying metadata");
1626 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1627 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1629 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1632 printf("SV[P]PPA\tnext\n");
1633 if(!FLAC__metadata_iterator_next(iterator))
1634 return die_("iterator ended early\n");
1635 our_current_position++;
1637 printf("SVP[P]PA\tnext\n");
1638 if(!FLAC__metadata_iterator_next(iterator))
1639 return die_("iterator ended early\n");
1640 our_current_position++;
1642 printf("SVPP[P]A\tnext\n");
1643 if(!FLAC__metadata_iterator_next(iterator))
1644 return die_("iterator ended early\n");
1645 our_current_position++;
1647 printf("SVPPP[A]\tinsert PADDING after\n");
1648 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1649 return die_("creating PADDING block");
1650 padding->length = 57;
1651 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1652 return die_("copying metadata");
1653 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1654 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1656 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1659 printf("SVPPPA[P]\tinsert PADDING before\n");
1660 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1661 return die_("creating PADDING block");
1662 padding->length = 99;
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("delete iterator\n");
1672 FLAC__metadata_iterator_delete(iterator);
1673 our_current_position = 0;
1675 printf("SVPPPAPP\tmerge padding\n");
1676 FLAC__metadata_chain_merge_padding(chain);
1677 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1678 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1679 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1680 delete_from_our_metadata_(7);
1681 delete_from_our_metadata_(4);
1682 delete_from_our_metadata_(3);
1684 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1685 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1686 if(!compare_chain_(chain, 0, 0))
1688 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1691 printf("SVPAP\tsort padding\n");
1692 FLAC__metadata_chain_sort_padding(chain);
1693 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1694 delete_from_our_metadata_(2);
1696 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1697 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1698 if(!compare_chain_(chain, 0, 0))
1700 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1703 printf("create iterator\n");
1704 if(0 == (iterator = FLAC__metadata_iterator_new()))
1705 return die_("allocating memory for iterator");
1707 our_current_position = 0;
1709 FLAC__metadata_iterator_init(iterator, chain);
1711 printf("[S]VAP\tnext\n");
1712 if(!FLAC__metadata_iterator_next(iterator))
1713 return die_("iterator ended early\n");
1714 our_current_position++;
1716 printf("S[V]AP\tnext\n");
1717 if(!FLAC__metadata_iterator_next(iterator))
1718 return die_("iterator ended early\n");
1719 our_current_position++;
1721 printf("SV[A]P\tdelete middle block, replace with padding\n");
1722 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1723 return die_("creating PADDING block");
1724 padding->length = 71;
1725 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1726 return die_("copying object");
1727 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1728 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1730 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1733 printf("S[V]PP\tnext\n");
1734 if(!FLAC__metadata_iterator_next(iterator))
1735 return die_("iterator ended early\n");
1736 our_current_position++;
1738 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1739 delete_from_our_metadata_(our_current_position--);
1740 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1741 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1743 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1746 printf("S[V]P\tnext\n");
1747 if(!FLAC__metadata_iterator_next(iterator))
1748 return die_("iterator ended early\n");
1749 our_current_position++;
1751 printf("SV[P]\tdelete last block, replace with padding\n");
1752 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1753 return die_("creating PADDING block");
1754 padding->length = 219;
1755 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1756 return die_("copying object");
1757 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1758 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1760 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1763 printf("S[V]P\tnext\n");
1764 if(!FLAC__metadata_iterator_next(iterator))
1765 return die_("iterator ended early\n");
1766 our_current_position++;
1768 printf("SV[P]\tdelete last block, don't replace with padding\n");
1769 delete_from_our_metadata_(our_current_position--);
1770 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1771 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1773 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1776 printf("S[V]\tprev\n");
1777 if(!FLAC__metadata_iterator_prev(iterator))
1778 return die_("iterator ended early\n");
1779 our_current_position--;
1781 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1782 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1783 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1785 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1788 printf("delete iterator\n");
1789 FLAC__metadata_iterator_delete(iterator);
1790 our_current_position = 0;
1792 printf("SV\tmerge padding\n");
1793 FLAC__metadata_chain_merge_padding(chain);
1795 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1796 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1797 if(!compare_chain_(chain, 0, 0))
1799 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1802 printf("SV\tsort padding\n");
1803 FLAC__metadata_chain_sort_padding(chain);
1805 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1806 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1807 if(!compare_chain_(chain, 0, 0))
1809 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1812 printf("delete chain\n");
1814 FLAC__metadata_chain_delete(chain);
1816 if(!remove_file_(flacfile_))
1822 static FLAC__bool test_level_2_misc_()
1824 FLAC__Metadata_Iterator *iterator;
1825 FLAC__Metadata_Chain *chain;
1826 FLAC__IOCallbacks callbacks;
1828 memset(&callbacks, 0, sizeof(callbacks));
1829 callbacks.read = (FLAC__IOCallback_Read)fread;
1830 #ifdef FLAC__VALGRIND_TESTING
1831 callbacks.write = chain_write_cb_;
1833 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1835 callbacks.seek = chain_seek_cb_;
1836 callbacks.tell = chain_tell_cb_;
1837 callbacks.eof = chain_eof_cb_;
1839 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1841 printf("generate file\n");
1843 if(!generate_file_())
1846 printf("create chain\n");
1848 if(0 == (chain = FLAC__metadata_chain_new()))
1849 return die_("allocating chain");
1851 printf("read chain (filename-based)\n");
1853 if(!FLAC__metadata_chain_read(chain, flacfile_))
1854 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1856 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1858 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1859 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1860 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1861 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1862 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1865 printf("read chain (filename-based)\n");
1867 if(!FLAC__metadata_chain_read(chain, flacfile_))
1868 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1870 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1872 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1873 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1874 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1875 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1876 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1879 printf("read chain (callback-based)\n");
1881 FILE *file = fopen(flacfile_, "rb");
1883 return die_("opening file");
1884 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1886 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1891 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1893 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1894 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1895 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1896 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1897 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1900 printf("read chain (callback-based)\n");
1902 FILE *file = fopen(flacfile_, "rb");
1904 return die_("opening file");
1905 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1907 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1912 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1914 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1915 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1917 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1919 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1921 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1922 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1923 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1924 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1925 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1928 printf("read chain (callback-based)\n");
1930 FILE *file = fopen(flacfile_, "rb");
1932 return die_("opening file");
1933 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1935 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1940 printf("create iterator\n");
1941 if(0 == (iterator = FLAC__metadata_iterator_new()))
1942 return die_("allocating memory for iterator");
1944 FLAC__metadata_iterator_init(iterator, chain);
1946 printf("[S]VP\tnext\n");
1947 if(!FLAC__metadata_iterator_next(iterator))
1948 return die_("iterator ended early\n");
1950 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1951 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1952 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1954 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1956 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1957 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1959 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
1961 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1963 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1964 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1965 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1966 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1967 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1970 printf("delete iterator\n");
1972 FLAC__metadata_iterator_delete(iterator);
1974 printf("delete chain\n");
1976 FLAC__metadata_chain_delete(chain);
1978 if(!remove_file_(flacfile_))
1984 FLAC__bool test_metadata_file_manipulation()
1986 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1988 our_metadata_.num_blocks = 0;
1990 if(!test_level_0_())
1993 if(!test_level_1_())
1996 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
1998 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2000 if(!test_level_2_misc_())