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 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, "w+b")))
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_;
292 callbacks.close = (FLAC__IOCallback_Close)fclose;
294 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
296 FILE *file, *tempfile;
298 if(preserve_file_stats) {
299 if(!get_file_stats_(filename, &stats))
302 if(0 == (file = fopen(filename, "rb")))
303 return false; /*@@@ chain status still says OK though */
304 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
306 cleanup_tempfile_(&tempfile, &tempfilename);
307 return false; /*@@@ chain status still says OK though */
309 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks))
311 file = tempfile = 0; /* FLAC__metadata_chain_write_with_callbacks_and_tempfile() always closes the file handles */
312 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
314 if(preserve_file_stats)
315 set_file_stats_(filename, &stats);
318 FILE *file = fopen(filename, "r+b");
320 return false; /*@@@ chain status still says OK though */
321 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
329 static FLAC__bool chain_read_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
332 return FLAC__metadata_chain_read(chain, flacfile_);
334 FLAC__IOCallbacks callbacks;
336 memset(&callbacks, 0, sizeof(callbacks));
337 callbacks.read = (FLAC__IOCallback_Read)fread;
338 callbacks.seek = chain_seek_cb_;
339 callbacks.tell = chain_tell_cb_;
340 callbacks.close = (FLAC__IOCallback_Close)fclose;
343 FILE *file = fopen(filename, "rb");
345 return false; /*@@@ chain status still says OK though */
346 return FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
351 /* function for comparing our metadata to a FLAC__Metadata_Chain */
353 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
356 FLAC__Metadata_Iterator *iterator;
357 FLAC__StreamMetadata *block;
358 FLAC__bool next_ok = true;
360 FLAC__ASSERT(0 != chain);
362 printf("\tcomparing chain... ");
365 if(0 == (iterator = FLAC__metadata_iterator_new()))
366 return die_("allocating memory for iterator");
368 FLAC__metadata_iterator_init(iterator, chain);
375 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
376 FLAC__metadata_iterator_delete(iterator);
377 return die_("getting block from iterator");
380 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
381 FLAC__metadata_iterator_delete(iterator);
382 return die_("metadata block mismatch");
386 next_ok = FLAC__metadata_iterator_next(iterator);
387 } while(i < our_metadata_.num_blocks && next_ok);
389 FLAC__metadata_iterator_delete(iterator);
392 return die_("chain has more blocks than expected");
394 if(i < our_metadata_.num_blocks)
395 return die_("short block count in chain");
397 if(0 != current_block) {
398 printf("CURRENT_POSITION... ");
401 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
402 return die_("metadata block mismatch");
410 /* decoder callbacks for checking the file */
412 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
414 (void)decoder, (void)buffer, (void)client_data;
417 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
418 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
420 printf("content... ");
424 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
427 /* this version pays no attention to the metadata */
428 static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
430 (void)decoder, (void)metadata, (void)client_data;
432 printf("%d... ", mc_our_block_number_);
435 mc_our_block_number_++;
438 /* this version is used when we want to compare to our metadata copy */
439 static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
441 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
445 /* don't bother checking if we've already hit an error */
446 if(dcd->error_occurred)
449 printf("%d... ", mc_our_block_number_);
452 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
453 (void)die_("got more metadata blocks than expected");
454 dcd->error_occurred = true;
457 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
458 (void)die_("metadata block mismatch");
459 dcd->error_occurred = true;
462 mc_our_block_number_++;
465 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
467 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
470 dcd->error_occurred = true;
471 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
474 static FLAC__bool generate_file_()
476 FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
477 FLAC__StreamMetadata *metadata[1];
479 printf("generating FLAC file for test\n");
481 while(our_metadata_.num_blocks > 0)
482 delete_from_our_metadata_(0);
484 streaminfo.is_last = false;
485 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
486 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
487 streaminfo.data.stream_info.min_blocksize = 576;
488 streaminfo.data.stream_info.max_blocksize = 576;
489 streaminfo.data.stream_info.min_framesize = 0;
490 streaminfo.data.stream_info.max_framesize = 0;
491 streaminfo.data.stream_info.sample_rate = 44100;
492 streaminfo.data.stream_info.channels = 1;
493 streaminfo.data.stream_info.bits_per_sample = 8;
494 streaminfo.data.stream_info.total_samples = 0;
495 memset(streaminfo.data.stream_info.md5sum, 0, 16);
498 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
499 vorbiscomment.is_last = false;
500 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
501 vorbiscomment.length = (4 + vendor_string_length) + 4;
502 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
503 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length);
504 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length);
505 vorbiscomment.data.vorbis_comment.num_comments = 0;
506 vorbiscomment.data.vorbis_comment.comments = 0;
509 padding.is_last = true;
510 padding.type = FLAC__METADATA_TYPE_PADDING;
511 padding.length = 1234;
513 metadata[0] = &padding;
516 !insert_to_our_metadata_(&streaminfo, 0, /*copy=*/true) ||
517 !insert_to_our_metadata_(&vorbiscomment, 1, /*copy=*/true) ||
518 !insert_to_our_metadata_(&padding, 2, /*copy=*/true)
520 return die_("priming our metadata");
522 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
523 return die_("creating the encoded file");
525 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
530 static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
532 FLAC__FileDecoder *decoder;
533 decoder_client_struct decoder_client_data;
535 FLAC__ASSERT(0 != filename);
536 FLAC__ASSERT(0 != metadata_callback);
538 mc_our_block_number_ = 0;
539 decoder_client_data.error_occurred = false;
541 printf("\ttesting '%s'... ", filename);
544 if(0 == (decoder = FLAC__file_decoder_new()))
545 return die_("couldn't allocate decoder instance");
547 FLAC__file_decoder_set_md5_checking(decoder, true);
548 FLAC__file_decoder_set_filename(decoder, filename);
549 FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
550 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
551 FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
552 FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
553 FLAC__file_decoder_set_metadata_respond_all(decoder);
554 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
555 FLAC__file_decoder_finish(decoder);
556 FLAC__file_decoder_delete(decoder);
557 return die_("initializing decoder\n");
559 if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
560 FLAC__file_decoder_finish(decoder);
561 FLAC__file_decoder_delete(decoder);
562 return die_("decoding file\n");
565 FLAC__file_decoder_finish(decoder);
566 FLAC__file_decoder_delete(decoder);
568 if(decoder_client_data.error_occurred)
571 if(mc_our_block_number_ != our_metadata_.num_blocks)
572 return die_("short metadata block count");
578 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
580 if(!grabbag__file_change_stats(filename, read_only))
581 return die_("during grabbag__file_change_stats()");
586 static FLAC__bool remove_file_(const char *filename)
588 while(our_metadata_.num_blocks > 0)
589 delete_from_our_metadata_(0);
591 if(!grabbag__file_remove_file(filename))
592 return die_("removing file");
597 static FLAC__bool test_level_0_()
599 FLAC__StreamMetadata streaminfo;
601 printf("\n\n++++++ testing level 0 interface\n");
603 if(!generate_file_())
606 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
609 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
610 return die_("during FLAC__metadata_get_streaminfo()");
612 /* check to see if some basic data matches (c.f. generate_file_()) */
613 if(streaminfo.data.stream_info.channels != 1)
614 return die_("mismatch in streaminfo.data.stream_info.channels");
615 if(streaminfo.data.stream_info.bits_per_sample != 8)
616 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
617 if(streaminfo.data.stream_info.sample_rate != 44100)
618 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
619 if(streaminfo.data.stream_info.min_blocksize != 576)
620 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
621 if(streaminfo.data.stream_info.max_blocksize != 576)
622 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
624 if(!remove_file_(flacfile_))
630 static FLAC__bool test_level_1_()
632 FLAC__Metadata_SimpleIterator *iterator;
633 FLAC__StreamMetadata *block, *app, *padding;
634 FLAC__byte data[1000];
635 unsigned our_current_position = 0;
637 /* initialize 'data' to avoid Valgrind errors */
638 memset(data, 0, sizeof(data));
640 printf("\n\n++++++ testing level 1 interface\n");
642 /************************************************************/
644 printf("simple iterator on read-only file\n");
646 if(!generate_file_())
649 if(!change_stats_(flacfile_, /*read_only=*/true))
652 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
655 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
656 return die_("FLAC__metadata_simple_iterator_new()");
658 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
659 return die_("FLAC__metadata_simple_iterator_init() returned false");
661 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
662 if(FLAC__metadata_simple_iterator_is_writable(iterator))
663 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
665 printf("iterate forwards\n");
667 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
668 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
669 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
670 return die_("getting block 0");
671 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
672 return die_("expected STREAMINFO type");
674 return die_("expected is_last to be false");
675 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
676 return die_("bad STREAMINFO length");
677 /* check to see if some basic data matches (c.f. generate_file_()) */
678 if(block->data.stream_info.channels != 1)
679 return die_("mismatch in channels");
680 if(block->data.stream_info.bits_per_sample != 8)
681 return die_("mismatch in bits_per_sample");
682 if(block->data.stream_info.sample_rate != 44100)
683 return die_("mismatch in sample_rate");
684 if(block->data.stream_info.min_blocksize != 576)
685 return die_("mismatch in min_blocksize");
686 if(block->data.stream_info.max_blocksize != 576)
687 return die_("mismatch in max_blocksize");
688 FLAC__metadata_object_delete(block);
690 if(!FLAC__metadata_simple_iterator_next(iterator))
691 return die_("forward iterator ended early");
692 our_current_position++;
694 if(!FLAC__metadata_simple_iterator_next(iterator))
695 return die_("forward iterator ended early");
696 our_current_position++;
698 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
699 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
700 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
701 return die_("getting block 2");
702 if(block->type != FLAC__METADATA_TYPE_PADDING)
703 return die_("expected PADDING type");
705 return die_("expected is_last to be true");
706 /* check to see if some basic data matches (c.f. generate_file_()) */
707 if(block->length != 1234)
708 return die_("bad PADDING length");
709 FLAC__metadata_object_delete(block);
711 if(FLAC__metadata_simple_iterator_next(iterator))
712 return die_("forward iterator returned true but should have returned false");
714 printf("iterate backwards\n");
715 if(!FLAC__metadata_simple_iterator_prev(iterator))
716 return die_("reverse iterator ended early");
717 if(!FLAC__metadata_simple_iterator_prev(iterator))
718 return die_("reverse iterator ended early");
719 if(FLAC__metadata_simple_iterator_prev(iterator))
720 return die_("reverse iterator returned true but should have returned false");
722 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
724 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
725 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
727 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
729 FLAC__metadata_simple_iterator_delete(iterator);
731 /************************************************************/
733 printf("simple iterator on writable file\n");
735 if(!change_stats_(flacfile_, /*read-only=*/false))
738 printf("creating APPLICATION block\n");
740 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
741 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
742 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
744 printf("creating PADDING block\n");
746 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
747 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
748 padding->length = 20;
750 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
751 return die_("FLAC__metadata_simple_iterator_new()");
753 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
754 return die_("FLAC__metadata_simple_iterator_init() returned false");
755 our_current_position = 0;
757 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
759 printf("[S]VP\ttry to write over STREAMINFO block...\n");
760 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
761 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
763 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
765 printf("[S]VP\tnext\n");
766 if(!FLAC__metadata_simple_iterator_next(iterator))
767 return die_("iterator ended early\n");
768 our_current_position++;
770 printf("S[V]P\tnext\n");
771 if(!FLAC__metadata_simple_iterator_next(iterator))
772 return die_("iterator ended early\n");
773 our_current_position++;
775 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
776 padding->length = 25;
777 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
778 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
779 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
782 printf("SVP[P]\tprev\n");
783 if(!FLAC__metadata_simple_iterator_prev(iterator))
784 return die_("iterator ended early\n");
785 our_current_position--;
787 printf("SV[P]P\tprev\n");
788 if(!FLAC__metadata_simple_iterator_prev(iterator))
789 return die_("iterator ended early\n");
790 our_current_position--;
792 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
793 padding->length = 30;
794 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
795 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
796 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
799 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
802 printf("SV[P]PP\tprev\n");
803 if(!FLAC__metadata_simple_iterator_prev(iterator))
804 return die_("iterator ended early\n");
805 our_current_position--;
807 printf("S[V]PPP\tprev\n");
808 if(!FLAC__metadata_simple_iterator_prev(iterator))
809 return die_("iterator ended early\n");
810 our_current_position--;
812 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
813 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
814 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
816 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
819 printf("[S]VPPP\tnext\n");
820 if(!FLAC__metadata_simple_iterator_next(iterator))
821 return die_("iterator ended early\n");
822 our_current_position++;
824 printf("S[V]PPP\tnext\n");
825 if(!FLAC__metadata_simple_iterator_next(iterator))
826 return die_("iterator ended early\n");
827 our_current_position++;
829 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
830 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
831 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
832 our_current_position--;
834 printf("S[V]PPP\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]PP\tdelete (middle block), don't replace with padding\n");
840 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
841 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
842 delete_from_our_metadata_(our_current_position--);
844 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
847 printf("S[V]PP\tnext\n");
848 if(!FLAC__metadata_simple_iterator_next(iterator))
849 return die_("iterator ended early\n");
850 our_current_position++;
852 printf("SV[P]P\tnext\n");
853 if(!FLAC__metadata_simple_iterator_next(iterator))
854 return die_("iterator ended early\n");
855 our_current_position++;
857 printf("SVP[P]\tdelete (last block), replace with padding\n");
858 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
859 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
860 our_current_position--;
862 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
865 printf("SV[P]P\tnext\n");
866 if(!FLAC__metadata_simple_iterator_next(iterator))
867 return die_("iterator ended early\n");
868 our_current_position++;
870 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
871 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
872 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
873 delete_from_our_metadata_(our_current_position--);
875 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
878 printf("SV[P]\tprev\n");
879 if(!FLAC__metadata_simple_iterator_prev(iterator))
880 return die_("iterator ended early\n");
881 our_current_position--;
883 printf("S[V]P\tprev\n");
884 if(!FLAC__metadata_simple_iterator_prev(iterator))
885 return die_("iterator ended early\n");
886 our_current_position--;
888 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
889 FLAC__ASSERT(our_current_position == 0);
890 block = FLAC__metadata_simple_iterator_get_block(iterator);
891 block->data.stream_info.sample_rate = 32000;
892 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
893 return die_("copying object");
894 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
895 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
896 FLAC__metadata_object_delete(block);
898 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
901 printf("[S]VP\tnext\n");
902 if(!FLAC__metadata_simple_iterator_next(iterator))
903 return die_("iterator ended early\n");
904 our_current_position++;
906 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
907 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
908 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
909 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
910 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
912 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
914 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
917 printf("SV[A]P\tnext\n");
918 if(!FLAC__metadata_simple_iterator_next(iterator))
919 return die_("iterator ended early\n");
920 our_current_position++;
922 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
923 app->data.application.id[0] = 'f'; /* twiddle the id */
924 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
925 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
926 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
928 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
930 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
933 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
934 app->data.application.id[0] = 'g'; /* twiddle the id */
935 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
936 return die_("setting APPLICATION data");
937 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
938 return die_("copying object");
939 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
940 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
942 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
945 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
946 app->data.application.id[0] = 'h'; /* twiddle the id */
947 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
948 return die_("setting APPLICATION data");
949 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
950 return die_("copying object");
951 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
952 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
954 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
957 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
958 app->data.application.id[0] = 'i'; /* twiddle the id */
959 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
960 return die_("setting APPLICATION data");
961 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
962 return die_("copying object");
963 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
964 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
965 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
967 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
970 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
971 app->data.application.id[0] = 'j'; /* twiddle the id */
972 if(!FLAC__metadata_object_application_set_data(app, data, 23, 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(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
977 return die_("copying object");
978 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
979 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
980 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
982 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
985 printf("SVA[A]PP\tnext\n");
986 if(!FLAC__metadata_simple_iterator_next(iterator))
987 return die_("iterator ended early\n");
988 our_current_position++;
990 printf("SVAA[P]P\tnext\n");
991 if(!FLAC__metadata_simple_iterator_next(iterator))
992 return die_("iterator ended early\n");
993 our_current_position++;
995 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
997 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
998 return die_("copying object");
999 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1000 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1002 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1005 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1006 app->data.application.id[0] = 'k'; /* twiddle the id */
1007 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1008 return die_("copying object");
1009 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1010 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1012 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1015 printf("SVAAP[A]\tset PADDING (equal)\n");
1016 padding->length = 27;
1017 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1018 return die_("copying object");
1019 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1020 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1022 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1025 printf("SVAAP[P]\tprev\n");
1026 if(!FLAC__metadata_simple_iterator_prev(iterator))
1027 return die_("iterator ended early\n");
1028 our_current_position--;
1030 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1031 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1032 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1033 delete_from_our_metadata_(our_current_position--);
1035 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1038 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1039 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1040 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1041 delete_from_our_metadata_(our_current_position--);
1043 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1046 printf("SV[A]P\tnext\n");
1047 if(!FLAC__metadata_simple_iterator_next(iterator))
1048 return die_("iterator ended early\n");
1049 our_current_position++;
1051 printf("SVA[P]\tinsert PADDING after\n");
1052 padding->length = 5;
1053 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1054 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1055 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1058 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1061 printf("SVAP[P]\tprev\n");
1062 if(!FLAC__metadata_simple_iterator_prev(iterator))
1063 return die_("iterator ended early\n");
1064 our_current_position--;
1066 printf("SVA[P]P\tprev\n");
1067 if(!FLAC__metadata_simple_iterator_prev(iterator))
1068 return die_("iterator ended early\n");
1069 our_current_position--;
1071 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1072 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1073 return die_("setting APPLICATION data");
1074 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1075 return die_("copying object");
1076 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1077 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1079 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1082 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1083 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1084 return die_("setting APPLICATION data");
1085 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1086 return die_("copying object");
1087 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1088 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1090 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1093 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1094 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1095 return die_("setting APPLICATION data");
1096 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1097 return die_("copying object");
1098 our_metadata_.blocks[our_current_position+1]->length = 0;
1099 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1100 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1102 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1105 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1106 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1107 return die_("setting APPLICATION data");
1108 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1109 return die_("copying object");
1110 delete_from_our_metadata_(our_current_position+1);
1111 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1112 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1114 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1117 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1118 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1119 return die_("setting APPLICATION data");
1120 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1121 return die_("copying object");
1122 delete_from_our_metadata_(our_current_position+1);
1123 our_metadata_.blocks[our_current_position]->is_last = true;
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]\tset PADDING (equal size)\n");
1131 padding->length = app->length;
1132 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1133 return die_("copying object");
1134 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1135 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1137 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1140 printf("SV[P]\tinsert PADDING after\n");
1141 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1142 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1143 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1146 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1149 printf("SVP[P]\tinsert PADDING after\n");
1150 padding->length = 5;
1151 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1152 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1153 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1156 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1159 printf("SVPP[P]\tprev\n");
1160 if(!FLAC__metadata_simple_iterator_prev(iterator))
1161 return die_("iterator ended early\n");
1162 our_current_position--;
1164 printf("SVP[P]P\tprev\n");
1165 if(!FLAC__metadata_simple_iterator_prev(iterator))
1166 return die_("iterator ended early\n");
1167 our_current_position--;
1169 printf("SV[P]PP\tprev\n");
1170 if(!FLAC__metadata_simple_iterator_prev(iterator))
1171 return die_("iterator ended early\n");
1172 our_current_position--;
1174 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1175 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1176 return die_("setting APPLICATION data");
1177 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1178 return die_("copying object");
1179 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1180 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1182 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1185 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1186 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1187 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1188 delete_from_our_metadata_(our_current_position--);
1190 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1193 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1194 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1195 return die_("setting APPLICATION data");
1196 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1197 return die_("copying object");
1198 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1199 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1201 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1204 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1205 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1206 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1207 delete_from_our_metadata_(our_current_position--);
1209 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1212 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1213 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1214 return die_("setting APPLICATION data");
1215 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1216 return die_("copying object");
1217 delete_from_our_metadata_(our_current_position+1);
1218 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1219 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1221 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1224 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1225 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1226 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1227 delete_from_our_metadata_(our_current_position--);
1229 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1232 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1233 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1234 return die_("setting APPLICATION data");
1235 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1236 return die_("copying object");
1237 our_metadata_.blocks[our_current_position+1]->length = 0;
1238 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1239 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1241 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1244 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1245 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1246 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1247 delete_from_our_metadata_(our_current_position--);
1249 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1252 printf("S[V]PP\tnext\n");
1253 if(!FLAC__metadata_simple_iterator_next(iterator))
1254 return die_("iterator ended early\n");
1255 our_current_position++;
1257 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1258 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1259 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1260 delete_from_our_metadata_(our_current_position--);
1262 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1265 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1266 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1267 return die_("setting APPLICATION data");
1268 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1269 return die_("copying object");
1270 delete_from_our_metadata_(our_current_position+1);
1271 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1272 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1274 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1277 printf("delete simple iterator\n");
1279 FLAC__metadata_simple_iterator_delete(iterator);
1281 FLAC__metadata_object_delete(app);
1282 FLAC__metadata_object_delete(padding);
1284 if(!remove_file_(flacfile_))
1290 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1292 FLAC__Metadata_Iterator *iterator;
1293 FLAC__Metadata_Chain *chain;
1294 FLAC__StreamMetadata *block, *app, *padding;
1295 FLAC__byte data[2000];
1296 unsigned our_current_position;
1298 /* initialize 'data' to avoid Valgrind errors */
1299 memset(data, 0, sizeof(data));
1301 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1303 printf("generate read-only file\n");
1305 if(!generate_file_())
1308 if(!change_stats_(flacfile_, /*read_only=*/true))
1311 printf("create chain\n");
1313 if(0 == (chain = FLAC__metadata_chain_new()))
1314 return die_("allocating chain");
1316 printf("read chain\n");
1318 if(!chain_read_(chain, flacfile_, filename_based))
1319 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1321 printf("[S]VP\ttest initial metadata\n");
1323 if(!compare_chain_(chain, 0, 0))
1325 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1328 printf("switch file to read-write\n");
1330 if(!change_stats_(flacfile_, /*read-only=*/false))
1333 printf("create iterator\n");
1334 if(0 == (iterator = FLAC__metadata_iterator_new()))
1335 return die_("allocating memory for iterator");
1337 our_current_position = 0;
1339 FLAC__metadata_iterator_init(iterator, chain);
1341 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1342 return die_("getting block from iterator");
1344 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1346 printf("[S]VP\tmodify STREAMINFO, write\n");
1348 block->data.stream_info.sample_rate = 32000;
1349 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1350 return die_("copying object");
1352 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1353 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1354 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1356 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1359 printf("[S]VP\tnext\n");
1360 if(!FLAC__metadata_iterator_next(iterator))
1361 return die_("iterator ended early\n");
1362 our_current_position++;
1364 printf("S[V]P\tnext\n");
1365 if(!FLAC__metadata_iterator_next(iterator))
1366 return die_("iterator ended early\n");
1367 our_current_position++;
1369 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1370 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1371 return die_("getting block from iterator");
1372 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1373 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1374 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1375 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1376 return die_("setting APPLICATION data");
1377 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1378 return die_("copying object");
1379 if(!FLAC__metadata_iterator_set_block(iterator, app))
1380 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1382 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1383 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1384 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1386 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1389 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1390 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1391 return die_("copying object");
1392 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1393 return die_("setting APPLICATION data");
1394 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1395 return die_("copying object");
1396 if(!FLAC__metadata_iterator_set_block(iterator, app))
1397 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1399 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1400 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1401 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1403 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1406 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1407 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1408 return die_("copying object");
1409 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1410 return die_("setting APPLICATION data");
1411 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1412 return die_("copying object");
1413 if(!FLAC__metadata_iterator_set_block(iterator, app))
1414 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1416 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1417 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", 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("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1424 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1425 return die_("copying object");
1426 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1427 return die_("setting APPLICATION data");
1428 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1429 return die_("copying object");
1430 if(!FLAC__metadata_iterator_set_block(iterator, app))
1431 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1433 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1434 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1435 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1437 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1440 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1441 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1442 return die_("copying object");
1443 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1444 return die_("setting APPLICATION data");
1445 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1446 return die_("copying object");
1447 if(!FLAC__metadata_iterator_set_block(iterator, app))
1448 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1450 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1451 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1452 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1454 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1457 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1458 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1459 return die_("creating PADDING block");
1460 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1461 return die_("copying object");
1462 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1463 return die_("setting APPLICATION data");
1464 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1465 return die_("copying object");
1466 padding->length = 0;
1467 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1468 return die_("internal error");
1469 if(!FLAC__metadata_iterator_set_block(iterator, app))
1470 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1472 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1473 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1474 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1476 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1479 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1480 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1481 return die_("copying object");
1482 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1483 return die_("setting APPLICATION data");
1484 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1485 return die_("copying object");
1486 our_metadata_.blocks[our_current_position+1]->length = 13;
1487 if(!FLAC__metadata_iterator_set_block(iterator, app))
1488 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1490 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1491 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1492 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1494 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1497 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1498 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1499 return die_("copying object");
1500 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1501 return die_("setting APPLICATION data");
1502 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1503 return die_("copying object");
1504 if(!FLAC__metadata_iterator_set_block(iterator, app))
1505 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1507 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1508 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1509 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1511 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1514 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1515 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1516 return die_("copying object");
1517 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1518 return die_("setting APPLICATION data");
1519 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1520 return die_("copying object");
1521 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1522 if(!FLAC__metadata_iterator_set_block(iterator, app))
1523 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1525 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1526 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1527 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1529 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1532 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1533 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1534 return die_("copying object");
1535 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1536 return die_("setting APPLICATION data");
1537 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1538 return die_("copying object");
1539 delete_from_our_metadata_(our_current_position+1);
1540 if(!FLAC__metadata_iterator_set_block(iterator, app))
1541 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1543 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1544 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1545 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1547 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1550 printf("SV[A]\tprev\n");
1551 if(!FLAC__metadata_iterator_prev(iterator))
1552 return die_("iterator ended early\n");
1553 our_current_position--;
1555 printf("S[V]A\tprev\n");
1556 if(!FLAC__metadata_iterator_prev(iterator))
1557 return die_("iterator ended early\n");
1558 our_current_position--;
1560 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1561 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1562 return die_("creating PADDING block");
1563 padding->length = 30;
1564 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1565 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1567 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1569 printf("[S]VP\tnext\n");
1570 if(!FLAC__metadata_iterator_next(iterator))
1571 return die_("iterator ended early\n");
1572 our_current_position++;
1574 printf("S[V]A\tinsert PADDING after\n");
1575 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1576 return die_("copying metadata");
1577 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1578 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1580 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1583 printf("SV[P]A\tinsert PADDING before\n");
1584 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1585 return die_("creating PADDING block");
1586 padding->length = 17;
1587 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1588 return die_("copying metadata");
1589 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1590 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1592 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1595 printf("SV[P]PA\tinsert PADDING before\n");
1596 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1597 return die_("creating PADDING block");
1598 padding->length = 0;
1599 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1600 return die_("copying metadata");
1601 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1602 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1604 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1607 printf("SV[P]PPA\tnext\n");
1608 if(!FLAC__metadata_iterator_next(iterator))
1609 return die_("iterator ended early\n");
1610 our_current_position++;
1612 printf("SVP[P]PA\tnext\n");
1613 if(!FLAC__metadata_iterator_next(iterator))
1614 return die_("iterator ended early\n");
1615 our_current_position++;
1617 printf("SVPP[P]A\tnext\n");
1618 if(!FLAC__metadata_iterator_next(iterator))
1619 return die_("iterator ended early\n");
1620 our_current_position++;
1622 printf("SVPPP[A]\tinsert PADDING after\n");
1623 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1624 return die_("creating PADDING block");
1625 padding->length = 57;
1626 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1627 return die_("copying metadata");
1628 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1629 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1631 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1634 printf("SVPPPA[P]\tinsert PADDING before\n");
1635 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1636 return die_("creating PADDING block");
1637 padding->length = 99;
1638 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1639 return die_("copying metadata");
1640 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1641 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1643 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1646 printf("delete iterator\n");
1647 FLAC__metadata_iterator_delete(iterator);
1648 our_current_position = 0;
1650 printf("SVPPPAPP\tmerge padding\n");
1651 FLAC__metadata_chain_merge_padding(chain);
1652 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1653 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1654 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1655 delete_from_our_metadata_(7);
1656 delete_from_our_metadata_(4);
1657 delete_from_our_metadata_(3);
1659 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1660 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1661 if(!compare_chain_(chain, 0, 0))
1663 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1666 printf("SVPAP\tsort padding\n");
1667 FLAC__metadata_chain_sort_padding(chain);
1668 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1669 delete_from_our_metadata_(2);
1671 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1672 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1673 if(!compare_chain_(chain, 0, 0))
1675 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1678 printf("create iterator\n");
1679 if(0 == (iterator = FLAC__metadata_iterator_new()))
1680 return die_("allocating memory for iterator");
1682 our_current_position = 0;
1684 FLAC__metadata_iterator_init(iterator, chain);
1686 printf("[S]VAP\tnext\n");
1687 if(!FLAC__metadata_iterator_next(iterator))
1688 return die_("iterator ended early\n");
1689 our_current_position++;
1691 printf("S[V]AP\tnext\n");
1692 if(!FLAC__metadata_iterator_next(iterator))
1693 return die_("iterator ended early\n");
1694 our_current_position++;
1696 printf("SV[A]P\tdelete middle block, replace with padding\n");
1697 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1698 return die_("creating PADDING block");
1699 padding->length = 71;
1700 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1701 return die_("copying object");
1702 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1703 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1705 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1708 printf("S[V]PP\tnext\n");
1709 if(!FLAC__metadata_iterator_next(iterator))
1710 return die_("iterator ended early\n");
1711 our_current_position++;
1713 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1714 delete_from_our_metadata_(our_current_position--);
1715 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1716 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1718 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1721 printf("S[V]P\tnext\n");
1722 if(!FLAC__metadata_iterator_next(iterator))
1723 return die_("iterator ended early\n");
1724 our_current_position++;
1726 printf("SV[P]\tdelete last block, replace with padding\n");
1727 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1728 return die_("creating PADDING block");
1729 padding->length = 219;
1730 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1731 return die_("copying object");
1732 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1733 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1735 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1738 printf("S[V]P\tnext\n");
1739 if(!FLAC__metadata_iterator_next(iterator))
1740 return die_("iterator ended early\n");
1741 our_current_position++;
1743 printf("SV[P]\tdelete last block, don't replace with padding\n");
1744 delete_from_our_metadata_(our_current_position--);
1745 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1746 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1748 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1751 printf("S[V]\tprev\n");
1752 if(!FLAC__metadata_iterator_prev(iterator))
1753 return die_("iterator ended early\n");
1754 our_current_position--;
1756 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1757 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1758 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1760 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1763 printf("delete iterator\n");
1764 FLAC__metadata_iterator_delete(iterator);
1765 our_current_position = 0;
1767 printf("SV\tmerge padding\n");
1768 FLAC__metadata_chain_merge_padding(chain);
1770 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1771 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1772 if(!compare_chain_(chain, 0, 0))
1774 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1777 printf("SV\tsort padding\n");
1778 FLAC__metadata_chain_sort_padding(chain);
1780 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1781 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1782 if(!compare_chain_(chain, 0, 0))
1784 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1787 printf("delete chain\n");
1789 FLAC__metadata_chain_delete(chain);
1791 if(!remove_file_(flacfile_))
1797 FLAC__bool test_metadata_file_manipulation()
1799 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1801 our_metadata_.num_blocks = 0;
1803 if(!test_level_0_())
1806 if(!test_level_1_())
1809 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
1811 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */