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);
511 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length);
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;
608 printf("\n\n++++++ testing level 0 interface\n");
610 if(!generate_file_())
613 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
616 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
617 return die_("during FLAC__metadata_get_streaminfo()");
619 /* check to see if some basic data matches (c.f. generate_file_()) */
620 if(streaminfo.data.stream_info.channels != 1)
621 return die_("mismatch in streaminfo.data.stream_info.channels");
622 if(streaminfo.data.stream_info.bits_per_sample != 8)
623 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
624 if(streaminfo.data.stream_info.sample_rate != 44100)
625 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
626 if(streaminfo.data.stream_info.min_blocksize != 576)
627 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
628 if(streaminfo.data.stream_info.max_blocksize != 576)
629 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
631 if(!remove_file_(flacfile_))
637 static FLAC__bool test_level_1_()
639 FLAC__Metadata_SimpleIterator *iterator;
640 FLAC__StreamMetadata *block, *app, *padding;
641 FLAC__byte data[1000];
642 unsigned our_current_position = 0;
644 /* initialize 'data' to avoid Valgrind errors */
645 memset(data, 0, sizeof(data));
647 printf("\n\n++++++ testing level 1 interface\n");
649 /************************************************************/
651 printf("simple iterator on read-only file\n");
653 if(!generate_file_())
656 if(!change_stats_(flacfile_, /*read_only=*/true))
659 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
662 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
663 return die_("FLAC__metadata_simple_iterator_new()");
665 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
666 return die_("FLAC__metadata_simple_iterator_init() returned false");
668 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
669 if(FLAC__metadata_simple_iterator_is_writable(iterator))
670 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
672 printf("iterate forwards\n");
674 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
675 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
676 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
677 return die_("getting block 0");
678 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
679 return die_("expected STREAMINFO type");
681 return die_("expected is_last to be false");
682 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
683 return die_("bad STREAMINFO length");
684 /* check to see if some basic data matches (c.f. generate_file_()) */
685 if(block->data.stream_info.channels != 1)
686 return die_("mismatch in channels");
687 if(block->data.stream_info.bits_per_sample != 8)
688 return die_("mismatch in bits_per_sample");
689 if(block->data.stream_info.sample_rate != 44100)
690 return die_("mismatch in sample_rate");
691 if(block->data.stream_info.min_blocksize != 576)
692 return die_("mismatch in min_blocksize");
693 if(block->data.stream_info.max_blocksize != 576)
694 return die_("mismatch in max_blocksize");
695 FLAC__metadata_object_delete(block);
697 if(!FLAC__metadata_simple_iterator_next(iterator))
698 return die_("forward iterator ended early");
699 our_current_position++;
701 if(!FLAC__metadata_simple_iterator_next(iterator))
702 return die_("forward iterator ended early");
703 our_current_position++;
705 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
706 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
707 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
708 return die_("getting block 2");
709 if(block->type != FLAC__METADATA_TYPE_PADDING)
710 return die_("expected PADDING type");
712 return die_("expected is_last to be true");
713 /* check to see if some basic data matches (c.f. generate_file_()) */
714 if(block->length != 1234)
715 return die_("bad PADDING length");
716 FLAC__metadata_object_delete(block);
718 if(FLAC__metadata_simple_iterator_next(iterator))
719 return die_("forward iterator returned true but should have returned false");
721 printf("iterate backwards\n");
722 if(!FLAC__metadata_simple_iterator_prev(iterator))
723 return die_("reverse iterator ended early");
724 if(!FLAC__metadata_simple_iterator_prev(iterator))
725 return die_("reverse iterator ended early");
726 if(FLAC__metadata_simple_iterator_prev(iterator))
727 return die_("reverse iterator returned true but should have returned false");
729 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
731 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
732 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
734 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
736 FLAC__metadata_simple_iterator_delete(iterator);
738 /************************************************************/
740 printf("simple iterator on writable file\n");
742 if(!change_stats_(flacfile_, /*read-only=*/false))
745 printf("creating APPLICATION block\n");
747 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
748 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
749 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
751 printf("creating PADDING block\n");
753 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
754 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
755 padding->length = 20;
757 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
758 return die_("FLAC__metadata_simple_iterator_new()");
760 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
761 return die_("FLAC__metadata_simple_iterator_init() returned false");
762 our_current_position = 0;
764 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
766 printf("[S]VP\ttry to write over STREAMINFO block...\n");
767 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
768 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
770 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
772 printf("[S]VP\tnext\n");
773 if(!FLAC__metadata_simple_iterator_next(iterator))
774 return die_("iterator ended early\n");
775 our_current_position++;
777 printf("S[V]P\tnext\n");
778 if(!FLAC__metadata_simple_iterator_next(iterator))
779 return die_("iterator ended early\n");
780 our_current_position++;
782 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
783 padding->length = 25;
784 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
785 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
786 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
789 printf("SVP[P]\tprev\n");
790 if(!FLAC__metadata_simple_iterator_prev(iterator))
791 return die_("iterator ended early\n");
792 our_current_position--;
794 printf("SV[P]P\tprev\n");
795 if(!FLAC__metadata_simple_iterator_prev(iterator))
796 return die_("iterator ended early\n");
797 our_current_position--;
799 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
800 padding->length = 30;
801 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
802 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
803 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
806 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
809 printf("SV[P]PP\tprev\n");
810 if(!FLAC__metadata_simple_iterator_prev(iterator))
811 return die_("iterator ended early\n");
812 our_current_position--;
814 printf("S[V]PPP\tprev\n");
815 if(!FLAC__metadata_simple_iterator_prev(iterator))
816 return die_("iterator ended early\n");
817 our_current_position--;
819 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
820 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
821 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
823 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
826 printf("[S]VPPP\tnext\n");
827 if(!FLAC__metadata_simple_iterator_next(iterator))
828 return die_("iterator ended early\n");
829 our_current_position++;
831 printf("S[V]PPP\tnext\n");
832 if(!FLAC__metadata_simple_iterator_next(iterator))
833 return die_("iterator ended early\n");
834 our_current_position++;
836 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
837 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
838 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
839 our_current_position--;
841 printf("S[V]PPP\tnext\n");
842 if(!FLAC__metadata_simple_iterator_next(iterator))
843 return die_("iterator ended early\n");
844 our_current_position++;
846 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
847 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
848 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
849 delete_from_our_metadata_(our_current_position--);
851 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
854 printf("S[V]PP\tnext\n");
855 if(!FLAC__metadata_simple_iterator_next(iterator))
856 return die_("iterator ended early\n");
857 our_current_position++;
859 printf("SV[P]P\tnext\n");
860 if(!FLAC__metadata_simple_iterator_next(iterator))
861 return die_("iterator ended early\n");
862 our_current_position++;
864 printf("SVP[P]\tdelete (last block), replace with padding\n");
865 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
866 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
867 our_current_position--;
869 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
872 printf("SV[P]P\tnext\n");
873 if(!FLAC__metadata_simple_iterator_next(iterator))
874 return die_("iterator ended early\n");
875 our_current_position++;
877 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
878 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
879 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
880 delete_from_our_metadata_(our_current_position--);
882 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
885 printf("SV[P]\tprev\n");
886 if(!FLAC__metadata_simple_iterator_prev(iterator))
887 return die_("iterator ended early\n");
888 our_current_position--;
890 printf("S[V]P\tprev\n");
891 if(!FLAC__metadata_simple_iterator_prev(iterator))
892 return die_("iterator ended early\n");
893 our_current_position--;
895 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
896 FLAC__ASSERT(our_current_position == 0);
897 block = FLAC__metadata_simple_iterator_get_block(iterator);
898 block->data.stream_info.sample_rate = 32000;
899 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
900 return die_("copying object");
901 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
902 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
903 FLAC__metadata_object_delete(block);
905 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
908 printf("[S]VP\tnext\n");
909 if(!FLAC__metadata_simple_iterator_next(iterator))
910 return die_("iterator ended early\n");
911 our_current_position++;
913 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
914 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
915 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
916 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
917 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
919 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
921 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
924 printf("SV[A]P\tnext\n");
925 if(!FLAC__metadata_simple_iterator_next(iterator))
926 return die_("iterator ended early\n");
927 our_current_position++;
929 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
930 app->data.application.id[0] = 'f'; /* twiddle the id */
931 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
932 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
933 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
935 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
937 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
940 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
941 app->data.application.id[0] = 'g'; /* twiddle the id */
942 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
943 return die_("setting APPLICATION data");
944 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
945 return die_("copying object");
946 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
947 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
949 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
952 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
953 app->data.application.id[0] = 'h'; /* twiddle the id */
954 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
955 return die_("setting APPLICATION data");
956 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
957 return die_("copying object");
958 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
959 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
961 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
964 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
965 app->data.application.id[0] = 'i'; /* twiddle the id */
966 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
967 return die_("setting APPLICATION data");
968 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
969 return die_("copying object");
970 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
971 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
972 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
974 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
977 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
978 app->data.application.id[0] = 'j'; /* twiddle the id */
979 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
980 return die_("setting APPLICATION data");
981 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
982 return die_("copying object");
983 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
984 return die_("copying object");
985 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
986 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
987 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
989 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
992 printf("SVA[A]PP\tnext\n");
993 if(!FLAC__metadata_simple_iterator_next(iterator))
994 return die_("iterator ended early\n");
995 our_current_position++;
997 printf("SVAA[P]P\tnext\n");
998 if(!FLAC__metadata_simple_iterator_next(iterator))
999 return die_("iterator ended early\n");
1000 our_current_position++;
1002 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1003 padding->length = 5;
1004 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1005 return die_("copying object");
1006 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1007 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1009 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1012 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1013 app->data.application.id[0] = 'k'; /* twiddle the id */
1014 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1015 return die_("copying object");
1016 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1017 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1019 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1022 printf("SVAAP[A]\tset PADDING (equal)\n");
1023 padding->length = 27;
1024 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1025 return die_("copying object");
1026 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1027 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1029 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1032 printf("SVAAP[P]\tprev\n");
1033 if(!FLAC__metadata_simple_iterator_prev(iterator))
1034 return die_("iterator ended early\n");
1035 our_current_position--;
1037 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1038 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1039 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1040 delete_from_our_metadata_(our_current_position--);
1042 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1045 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1046 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1047 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1048 delete_from_our_metadata_(our_current_position--);
1050 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1053 printf("SV[A]P\tnext\n");
1054 if(!FLAC__metadata_simple_iterator_next(iterator))
1055 return die_("iterator ended early\n");
1056 our_current_position++;
1058 printf("SVA[P]\tinsert PADDING after\n");
1059 padding->length = 5;
1060 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1061 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1062 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1065 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1068 printf("SVAP[P]\tprev\n");
1069 if(!FLAC__metadata_simple_iterator_prev(iterator))
1070 return die_("iterator ended early\n");
1071 our_current_position--;
1073 printf("SVA[P]P\tprev\n");
1074 if(!FLAC__metadata_simple_iterator_prev(iterator))
1075 return die_("iterator ended early\n");
1076 our_current_position--;
1078 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1079 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1080 return die_("setting APPLICATION data");
1081 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1082 return die_("copying object");
1083 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1084 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1086 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1089 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1090 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1091 return die_("setting APPLICATION data");
1092 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1093 return die_("copying object");
1094 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1095 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1097 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1100 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1101 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1102 return die_("setting APPLICATION data");
1103 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1104 return die_("copying object");
1105 our_metadata_.blocks[our_current_position+1]->length = 0;
1106 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1107 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1109 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1112 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1113 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1114 return die_("setting APPLICATION data");
1115 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1116 return die_("copying object");
1117 delete_from_our_metadata_(our_current_position+1);
1118 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1119 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1121 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1124 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1125 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1126 return die_("setting APPLICATION data");
1127 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1128 return die_("copying object");
1129 delete_from_our_metadata_(our_current_position+1);
1130 our_metadata_.blocks[our_current_position]->is_last = true;
1131 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1132 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1134 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1137 printf("SV[A]\tset PADDING (equal size)\n");
1138 padding->length = app->length;
1139 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1140 return die_("copying object");
1141 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1142 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1144 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1147 printf("SV[P]\tinsert PADDING after\n");
1148 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1149 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1150 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1153 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1156 printf("SVP[P]\tinsert PADDING after\n");
1157 padding->length = 5;
1158 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1159 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1160 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1163 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1166 printf("SVPP[P]\tprev\n");
1167 if(!FLAC__metadata_simple_iterator_prev(iterator))
1168 return die_("iterator ended early\n");
1169 our_current_position--;
1171 printf("SVP[P]P\tprev\n");
1172 if(!FLAC__metadata_simple_iterator_prev(iterator))
1173 return die_("iterator ended early\n");
1174 our_current_position--;
1176 printf("SV[P]PP\tprev\n");
1177 if(!FLAC__metadata_simple_iterator_prev(iterator))
1178 return die_("iterator ended early\n");
1179 our_current_position--;
1181 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1182 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1183 return die_("setting APPLICATION data");
1184 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1185 return die_("copying object");
1186 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1187 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1189 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1192 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1193 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1194 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1195 delete_from_our_metadata_(our_current_position--);
1197 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1200 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1201 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1202 return die_("setting APPLICATION data");
1203 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1204 return die_("copying object");
1205 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1206 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1208 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1211 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1212 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1213 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1214 delete_from_our_metadata_(our_current_position--);
1216 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1219 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1220 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1221 return die_("setting APPLICATION data");
1222 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1223 return die_("copying object");
1224 delete_from_our_metadata_(our_current_position+1);
1225 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1226 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1228 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1231 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1232 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1233 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1234 delete_from_our_metadata_(our_current_position--);
1236 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1239 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1240 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1241 return die_("setting APPLICATION data");
1242 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1243 return die_("copying object");
1244 our_metadata_.blocks[our_current_position+1]->length = 0;
1245 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1246 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1248 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1251 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1252 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1253 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1254 delete_from_our_metadata_(our_current_position--);
1256 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1259 printf("S[V]PP\tnext\n");
1260 if(!FLAC__metadata_simple_iterator_next(iterator))
1261 return die_("iterator ended early\n");
1262 our_current_position++;
1264 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1265 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1266 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1267 delete_from_our_metadata_(our_current_position--);
1269 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1272 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1273 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1274 return die_("setting APPLICATION data");
1275 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1276 return die_("copying object");
1277 delete_from_our_metadata_(our_current_position+1);
1278 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1279 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1281 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1284 printf("delete simple iterator\n");
1286 FLAC__metadata_simple_iterator_delete(iterator);
1288 FLAC__metadata_object_delete(app);
1289 FLAC__metadata_object_delete(padding);
1291 if(!remove_file_(flacfile_))
1297 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1299 FLAC__Metadata_Iterator *iterator;
1300 FLAC__Metadata_Chain *chain;
1301 FLAC__StreamMetadata *block, *app, *padding;
1302 FLAC__byte data[2000];
1303 unsigned our_current_position;
1305 /* initialize 'data' to avoid Valgrind errors */
1306 memset(data, 0, sizeof(data));
1308 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1310 printf("generate read-only file\n");
1312 if(!generate_file_())
1315 if(!change_stats_(flacfile_, /*read_only=*/true))
1318 printf("create chain\n");
1320 if(0 == (chain = FLAC__metadata_chain_new()))
1321 return die_("allocating chain");
1323 printf("read chain\n");
1325 if(!read_chain_(chain, flacfile_, filename_based))
1326 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1328 printf("[S]VP\ttest initial metadata\n");
1330 if(!compare_chain_(chain, 0, 0))
1332 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1335 printf("switch file to read-write\n");
1337 if(!change_stats_(flacfile_, /*read-only=*/false))
1340 printf("create iterator\n");
1341 if(0 == (iterator = FLAC__metadata_iterator_new()))
1342 return die_("allocating memory for iterator");
1344 our_current_position = 0;
1346 FLAC__metadata_iterator_init(iterator, chain);
1348 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1349 return die_("getting block from iterator");
1351 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1353 printf("[S]VP\tmodify STREAMINFO, write\n");
1355 block->data.stream_info.sample_rate = 32000;
1356 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1357 return die_("copying object");
1359 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1360 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1361 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1363 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1366 printf("[S]VP\tnext\n");
1367 if(!FLAC__metadata_iterator_next(iterator))
1368 return die_("iterator ended early\n");
1369 our_current_position++;
1371 printf("S[V]P\tnext\n");
1372 if(!FLAC__metadata_iterator_next(iterator))
1373 return die_("iterator ended early\n");
1374 our_current_position++;
1376 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1377 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1378 return die_("getting block from iterator");
1379 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1380 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1381 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1382 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1383 return die_("setting APPLICATION data");
1384 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1385 return die_("copying object");
1386 if(!FLAC__metadata_iterator_set_block(iterator, app))
1387 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1389 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1390 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1391 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1393 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1396 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1397 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1398 return die_("copying object");
1399 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1400 return die_("setting APPLICATION data");
1401 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1402 return die_("copying object");
1403 if(!FLAC__metadata_iterator_set_block(iterator, app))
1404 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1406 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1407 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1408 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1410 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1413 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1414 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1415 return die_("copying object");
1416 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1417 return die_("setting APPLICATION data");
1418 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1419 return die_("copying object");
1420 if(!FLAC__metadata_iterator_set_block(iterator, app))
1421 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1423 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1424 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1425 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1427 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1430 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1431 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1432 return die_("copying object");
1433 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1434 return die_("setting APPLICATION data");
1435 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1436 return die_("copying object");
1437 if(!FLAC__metadata_iterator_set_block(iterator, app))
1438 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1440 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1441 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1442 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1444 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1447 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1448 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1449 return die_("copying object");
1450 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1451 return die_("setting APPLICATION data");
1452 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1453 return die_("copying object");
1454 if(!FLAC__metadata_iterator_set_block(iterator, app))
1455 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1457 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1458 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1459 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1461 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1464 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1465 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1466 return die_("creating PADDING block");
1467 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1468 return die_("copying object");
1469 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1470 return die_("setting APPLICATION data");
1471 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1472 return die_("copying object");
1473 padding->length = 0;
1474 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1475 return die_("internal error");
1476 if(!FLAC__metadata_iterator_set_block(iterator, app))
1477 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1479 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1480 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1481 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1483 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1486 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1487 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1488 return die_("copying object");
1489 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1490 return die_("setting APPLICATION data");
1491 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1492 return die_("copying object");
1493 our_metadata_.blocks[our_current_position+1]->length = 13;
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\tgrow APPLICATION, use padding, last block is padding, but delta is too small\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, 50, true))
1508 return die_("setting APPLICATION data");
1509 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1510 return die_("copying object");
1511 if(!FLAC__metadata_iterator_set_block(iterator, app))
1512 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1514 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1515 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1516 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1518 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1521 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1522 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1523 return die_("copying object");
1524 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1525 return die_("setting APPLICATION data");
1526 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1527 return die_("copying object");
1528 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
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 exact 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, 67, 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 delete_from_our_metadata_(our_current_position+1);
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]\tprev\n");
1558 if(!FLAC__metadata_iterator_prev(iterator))
1559 return die_("iterator ended early\n");
1560 our_current_position--;
1562 printf("S[V]A\tprev\n");
1563 if(!FLAC__metadata_iterator_prev(iterator))
1564 return die_("iterator ended early\n");
1565 our_current_position--;
1567 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1568 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1569 return die_("creating PADDING block");
1570 padding->length = 30;
1571 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1572 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1574 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1576 printf("[S]VP\tnext\n");
1577 if(!FLAC__metadata_iterator_next(iterator))
1578 return die_("iterator ended early\n");
1579 our_current_position++;
1581 printf("S[V]A\tinsert PADDING after\n");
1582 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1583 return die_("copying metadata");
1584 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1585 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1587 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1590 printf("SV[P]A\tinsert PADDING before\n");
1591 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1592 return die_("creating PADDING block");
1593 padding->length = 17;
1594 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1595 return die_("copying metadata");
1596 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1597 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1599 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1602 printf("SV[P]PA\tinsert PADDING before\n");
1603 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1604 return die_("creating PADDING block");
1605 padding->length = 0;
1606 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1607 return die_("copying metadata");
1608 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1609 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1611 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1614 printf("SV[P]PPA\tnext\n");
1615 if(!FLAC__metadata_iterator_next(iterator))
1616 return die_("iterator ended early\n");
1617 our_current_position++;
1619 printf("SVP[P]PA\tnext\n");
1620 if(!FLAC__metadata_iterator_next(iterator))
1621 return die_("iterator ended early\n");
1622 our_current_position++;
1624 printf("SVPP[P]A\tnext\n");
1625 if(!FLAC__metadata_iterator_next(iterator))
1626 return die_("iterator ended early\n");
1627 our_current_position++;
1629 printf("SVPPP[A]\tinsert PADDING after\n");
1630 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1631 return die_("creating PADDING block");
1632 padding->length = 57;
1633 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1634 return die_("copying metadata");
1635 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1636 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1638 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1641 printf("SVPPPA[P]\tinsert PADDING before\n");
1642 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1643 return die_("creating PADDING block");
1644 padding->length = 99;
1645 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1646 return die_("copying metadata");
1647 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1648 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1650 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1653 printf("delete iterator\n");
1654 FLAC__metadata_iterator_delete(iterator);
1655 our_current_position = 0;
1657 printf("SVPPPAPP\tmerge padding\n");
1658 FLAC__metadata_chain_merge_padding(chain);
1659 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1660 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1661 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1662 delete_from_our_metadata_(7);
1663 delete_from_our_metadata_(4);
1664 delete_from_our_metadata_(3);
1666 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1667 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1668 if(!compare_chain_(chain, 0, 0))
1670 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1673 printf("SVPAP\tsort padding\n");
1674 FLAC__metadata_chain_sort_padding(chain);
1675 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1676 delete_from_our_metadata_(2);
1678 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1679 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1680 if(!compare_chain_(chain, 0, 0))
1682 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1685 printf("create iterator\n");
1686 if(0 == (iterator = FLAC__metadata_iterator_new()))
1687 return die_("allocating memory for iterator");
1689 our_current_position = 0;
1691 FLAC__metadata_iterator_init(iterator, chain);
1693 printf("[S]VAP\tnext\n");
1694 if(!FLAC__metadata_iterator_next(iterator))
1695 return die_("iterator ended early\n");
1696 our_current_position++;
1698 printf("S[V]AP\tnext\n");
1699 if(!FLAC__metadata_iterator_next(iterator))
1700 return die_("iterator ended early\n");
1701 our_current_position++;
1703 printf("SV[A]P\tdelete middle block, replace with padding\n");
1704 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1705 return die_("creating PADDING block");
1706 padding->length = 71;
1707 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1708 return die_("copying object");
1709 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1710 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1712 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1715 printf("S[V]PP\tnext\n");
1716 if(!FLAC__metadata_iterator_next(iterator))
1717 return die_("iterator ended early\n");
1718 our_current_position++;
1720 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1721 delete_from_our_metadata_(our_current_position--);
1722 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1723 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1725 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1728 printf("S[V]P\tnext\n");
1729 if(!FLAC__metadata_iterator_next(iterator))
1730 return die_("iterator ended early\n");
1731 our_current_position++;
1733 printf("SV[P]\tdelete last block, replace with padding\n");
1734 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1735 return die_("creating PADDING block");
1736 padding->length = 219;
1737 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1738 return die_("copying object");
1739 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1740 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1742 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1745 printf("S[V]P\tnext\n");
1746 if(!FLAC__metadata_iterator_next(iterator))
1747 return die_("iterator ended early\n");
1748 our_current_position++;
1750 printf("SV[P]\tdelete last block, don't replace with padding\n");
1751 delete_from_our_metadata_(our_current_position--);
1752 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1753 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1755 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1758 printf("S[V]\tprev\n");
1759 if(!FLAC__metadata_iterator_prev(iterator))
1760 return die_("iterator ended early\n");
1761 our_current_position--;
1763 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1764 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1765 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1767 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1770 printf("delete iterator\n");
1771 FLAC__metadata_iterator_delete(iterator);
1772 our_current_position = 0;
1774 printf("SV\tmerge padding\n");
1775 FLAC__metadata_chain_merge_padding(chain);
1777 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1778 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1779 if(!compare_chain_(chain, 0, 0))
1781 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1784 printf("SV\tsort padding\n");
1785 FLAC__metadata_chain_sort_padding(chain);
1787 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1788 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1789 if(!compare_chain_(chain, 0, 0))
1791 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1794 printf("delete chain\n");
1796 FLAC__metadata_chain_delete(chain);
1798 if(!remove_file_(flacfile_))
1804 static FLAC__bool test_level_2_misc_()
1806 FLAC__Metadata_Iterator *iterator;
1807 FLAC__Metadata_Chain *chain;
1808 FLAC__IOCallbacks callbacks;
1810 memset(&callbacks, 0, sizeof(callbacks));
1811 callbacks.read = (FLAC__IOCallback_Read)fread;
1812 #ifdef FLAC__VALGRIND_TESTING
1813 callbacks.write = chain_write_cb_;
1815 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1817 callbacks.seek = chain_seek_cb_;
1818 callbacks.tell = chain_tell_cb_;
1819 callbacks.eof = chain_eof_cb_;
1821 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1823 printf("generate file\n");
1825 if(!generate_file_())
1828 printf("create chain\n");
1830 if(0 == (chain = FLAC__metadata_chain_new()))
1831 return die_("allocating chain");
1833 printf("read chain (filename-based)\n");
1835 if(!FLAC__metadata_chain_read(chain, flacfile_))
1836 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1838 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1840 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1841 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1842 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1843 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1844 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1847 printf("read chain (filename-based)\n");
1849 if(!FLAC__metadata_chain_read(chain, flacfile_))
1850 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1852 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1854 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1855 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1856 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1857 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1858 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1861 printf("read chain (callback-based)\n");
1863 FILE *file = fopen(flacfile_, "rb");
1865 return die_("opening file");
1866 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1868 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1873 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1875 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1876 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1877 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1878 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1879 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1882 printf("read chain (callback-based)\n");
1884 FILE *file = fopen(flacfile_, "rb");
1886 return die_("opening file");
1887 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1889 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1894 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1896 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1897 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1899 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1901 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1903 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1904 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1905 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1906 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1907 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1910 printf("read chain (callback-based)\n");
1912 FILE *file = fopen(flacfile_, "rb");
1914 return die_("opening file");
1915 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1917 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1922 printf("create iterator\n");
1923 if(0 == (iterator = FLAC__metadata_iterator_new()))
1924 return die_("allocating memory for iterator");
1926 FLAC__metadata_iterator_init(iterator, chain);
1928 printf("[S]VP\tnext\n");
1929 if(!FLAC__metadata_iterator_next(iterator))
1930 return die_("iterator ended early\n");
1932 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1933 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1934 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1936 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1938 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1939 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1941 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
1943 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1945 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1946 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1947 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1948 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1949 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1952 printf("delete iterator\n");
1954 FLAC__metadata_iterator_delete(iterator);
1956 printf("delete chain\n");
1958 FLAC__metadata_chain_delete(chain);
1960 if(!remove_file_(flacfile_))
1966 FLAC__bool test_metadata_file_manipulation()
1968 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1970 our_metadata_.num_blocks = 0;
1972 if(!test_level_0_())
1975 if(!test_level_1_())
1978 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
1980 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
1982 if(!test_level_2_misc_())