1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <stdlib.h> /* for malloc() */
25 #if defined _MSC_VER || defined __MINGW32__
26 #include <sys/utime.h> /* for utime() */
27 #include <io.h> /* for chmod() */
28 //@@@ [2G limit] hacks for MSVC6
32 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
33 #include <utime.h> /* for utime() */
34 #include <unistd.h> /* for chown(), unlink() */
36 #include <sys/stat.h> /* for stat(), maybe chmod() */
37 #include "FLAC/assert.h"
38 #include "FLAC/stream_decoder.h"
39 #include "FLAC/metadata.h"
40 #include "share/grabbag.h"
41 #include "test_libs_common/file_utils_flac.h"
42 #include "test_libs_common/metadata_utils.h"
45 /******************************************************************************
46 The general strategy of these tests (for interface levels 1 and 2) is
47 to create a dummy FLAC file with a known set of initial metadata
48 blocks, then keep a mirror locally of what we expect the metadata to be
49 after each operation. Then testing becomes a simple matter of running
50 a FLAC__StreamDecoder over the dummy file after each operation, comparing
51 the decoded metadata to what's in our local copy. If there are any
52 differences in the metadata, or the actual audio data is corrupted, we
53 will catch it while decoding.
54 ******************************************************************************/
57 FLAC__bool error_occurred;
58 } decoder_client_struct;
61 FLAC__StreamMetadata *blocks[64];
63 } our_metadata_struct;
65 static const char *flacfile_ = "metadata.flac";
67 /* our copy of the metadata in flacfile_ */
68 static our_metadata_struct our_metadata_;
70 /* the current block number that corresponds to the position of the iterator we are testing */
71 static unsigned mc_our_block_number_ = 0;
73 static FLAC__bool die_(const char *msg)
75 printf("ERROR: %s\n", msg);
79 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
81 printf("ERROR: %s\n", msg);
82 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
86 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
88 printf("ERROR: %s\n", msg);
89 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
93 static void *malloc_or_die_(size_t size)
95 void *x = malloc(size);
97 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
103 /* functions for working with our metadata copy */
105 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
108 FLAC__StreamMetadata *obj = block;
109 FLAC__ASSERT(position < our_metadata_.num_blocks);
111 if(0 == (obj = FLAC__metadata_object_clone(block)))
112 return die_("during FLAC__metadata_object_clone()");
114 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
115 our_metadata_.blocks[position] = obj;
117 /* set the is_last flags */
118 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
119 our_metadata_.blocks[i]->is_last = false;
120 our_metadata_.blocks[i]->is_last = true;
125 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
128 FLAC__StreamMetadata *obj = block;
130 if(0 == (obj = FLAC__metadata_object_clone(block)))
131 return die_("during FLAC__metadata_object_clone()");
133 if(position > our_metadata_.num_blocks) {
134 position = our_metadata_.num_blocks;
137 for(i = our_metadata_.num_blocks; i > position; i--)
138 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
140 our_metadata_.blocks[position] = obj;
141 our_metadata_.num_blocks++;
143 /* set the is_last flags */
144 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
145 our_metadata_.blocks[i]->is_last = false;
146 our_metadata_.blocks[i]->is_last = true;
151 static void delete_from_our_metadata_(unsigned position)
154 FLAC__ASSERT(position < our_metadata_.num_blocks);
155 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
156 for(i = position; i < our_metadata_.num_blocks - 1; i++)
157 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
158 our_metadata_.num_blocks--;
160 /* set the is_last flags */
161 if(our_metadata_.num_blocks > 0) {
162 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
163 our_metadata_.blocks[i]->is_last = false;
164 our_metadata_.blocks[i]->is_last = true;
169 * This wad of functions supports filename- and callback-based chain reading/writing.
170 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
172 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
174 static const char *tempfile_suffix = ".metadata_edit";
176 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
178 strcpy(*tempfilename, filename);
179 strcat(*tempfilename, tempfile_suffix);
181 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
187 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
190 (void)fclose(*tempfile);
194 if(0 != *tempfilename) {
195 (void)unlink(*tempfilename);
201 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
203 FLAC__ASSERT(0 != filename);
204 FLAC__ASSERT(0 != tempfile);
205 FLAC__ASSERT(0 != tempfilename);
206 FLAC__ASSERT(0 != *tempfilename);
209 (void)fclose(*tempfile);
213 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
214 /* on some flavors of windows, rename() will fail if the destination already exists */
215 if(unlink(filename) < 0) {
216 cleanup_tempfile_(tempfile, tempfilename);
221 if(0 != rename(*tempfilename, filename)) {
222 cleanup_tempfile_(tempfile, tempfilename);
226 cleanup_tempfile_(tempfile, tempfilename);
231 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
233 FLAC__ASSERT(0 != filename);
234 FLAC__ASSERT(0 != stats);
235 return (0 == stat(filename, stats));
238 void set_file_stats_(const char *filename, struct stat *stats)
240 struct utimbuf srctime;
242 FLAC__ASSERT(0 != filename);
243 FLAC__ASSERT(0 != stats);
245 srctime.actime = stats->st_atime;
246 srctime.modtime = stats->st_mtime;
247 (void)chmod(filename, stats->st_mode);
248 (void)utime(filename, &srctime);
249 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
250 (void)chown(filename, stats->st_uid, -1);
251 (void)chown(filename, -1, stats->st_gid);
255 #ifdef FLAC__VALGRIND_TESTING
256 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
258 FILE *stream = (FILE*)handle;
259 size_t ret = fwrite(ptr, size, nmemb, stream);
266 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
268 off_t o = (off_t)offset;
269 FLAC__ASSERT(offset == o);
270 return fseeko((FILE*)handle, o, whence);
273 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
275 return ftello((FILE*)handle);
278 static int chain_eof_cb_(FLAC__IOHandle handle)
280 return feof((FILE*)handle);
283 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)
286 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
288 FLAC__IOCallbacks callbacks;
290 memset(&callbacks, 0, sizeof(callbacks));
291 callbacks.read = (FLAC__IOCallback_Read)fread;
292 #ifdef FLAC__VALGRIND_TESTING
293 callbacks.write = chain_write_cb_;
295 callbacks.write = (FLAC__IOCallback_Write)fwrite;
297 callbacks.seek = chain_seek_cb_;
298 callbacks.eof = chain_eof_cb_;
300 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
302 FILE *file, *tempfile;
304 if(preserve_file_stats) {
305 if(!get_file_stats_(filename, &stats))
308 if(0 == (file = fopen(filename, "rb")))
309 return false; /*@@@ chain status still says OK though */
310 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
312 cleanup_tempfile_(&tempfile, &tempfilename);
313 return false; /*@@@ chain status still says OK though */
315 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
323 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
325 if(preserve_file_stats)
326 set_file_stats_(filename, &stats);
329 FILE *file = fopen(filename, "r+b");
331 return false; /*@@@ chain status still says OK though */
332 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
341 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
344 return FLAC__metadata_chain_read(chain, flacfile_);
346 FLAC__IOCallbacks callbacks;
348 memset(&callbacks, 0, sizeof(callbacks));
349 callbacks.read = (FLAC__IOCallback_Read)fread;
350 callbacks.seek = chain_seek_cb_;
351 callbacks.tell = chain_tell_cb_;
355 FILE *file = fopen(filename, "rb");
357 return false; /*@@@ chain status still says OK though */
358 ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
365 /* function for comparing our metadata to a FLAC__Metadata_Chain */
367 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
370 FLAC__Metadata_Iterator *iterator;
371 FLAC__StreamMetadata *block;
372 FLAC__bool next_ok = true;
374 FLAC__ASSERT(0 != chain);
376 printf("\tcomparing chain... ");
379 if(0 == (iterator = FLAC__metadata_iterator_new()))
380 return die_("allocating memory for iterator");
382 FLAC__metadata_iterator_init(iterator, chain);
389 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
390 FLAC__metadata_iterator_delete(iterator);
391 return die_("getting block from iterator");
394 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
395 FLAC__metadata_iterator_delete(iterator);
396 return die_("metadata block mismatch");
400 next_ok = FLAC__metadata_iterator_next(iterator);
401 } while(i < our_metadata_.num_blocks && next_ok);
403 FLAC__metadata_iterator_delete(iterator);
406 return die_("chain has more blocks than expected");
408 if(i < our_metadata_.num_blocks)
409 return die_("short block count in chain");
411 if(0 != current_block) {
412 printf("CURRENT_POSITION... ");
415 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
416 return die_("metadata block mismatch");
424 /* decoder callbacks for checking the file */
426 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
428 (void)decoder, (void)buffer, (void)client_data;
431 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
432 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
434 printf("content... ");
438 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
441 /* this version pays no attention to the metadata */
442 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
444 (void)decoder, (void)metadata, (void)client_data;
446 printf("%d... ", mc_our_block_number_);
449 mc_our_block_number_++;
452 /* this version is used when we want to compare to our metadata copy */
453 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
455 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
459 /* don't bother checking if we've already hit an error */
460 if(dcd->error_occurred)
463 printf("%d... ", mc_our_block_number_);
466 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
467 (void)die_("got more metadata blocks than expected");
468 dcd->error_occurred = true;
471 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
472 (void)die_("metadata block mismatch");
473 dcd->error_occurred = true;
476 mc_our_block_number_++;
479 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
481 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
484 dcd->error_occurred = true;
485 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
488 static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
490 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
491 FLAC__StreamMetadata *metadata[3];
492 unsigned i = 0, n = 0;
494 printf("generating FLAC file for test\n");
496 while(our_metadata_.num_blocks > 0)
497 delete_from_our_metadata_(0);
499 streaminfo.is_last = false;
500 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
501 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
502 streaminfo.data.stream_info.min_blocksize = 576;
503 streaminfo.data.stream_info.max_blocksize = 576;
504 streaminfo.data.stream_info.min_framesize = 0;
505 streaminfo.data.stream_info.max_framesize = 0;
506 streaminfo.data.stream_info.sample_rate = 44100;
507 streaminfo.data.stream_info.channels = 1;
508 streaminfo.data.stream_info.bits_per_sample = 8;
509 streaminfo.data.stream_info.total_samples = 0;
510 memset(streaminfo.data.stream_info.md5sum, 0, 16);
513 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
514 vorbiscomment.is_last = false;
515 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
516 vorbiscomment.length = (4 + vendor_string_length) + 4;
517 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
518 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
519 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
520 vorbiscomment.data.vorbis_comment.num_comments = 0;
521 vorbiscomment.data.vorbis_comment.comments = 0;
525 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
526 return die_("priming our metadata");
527 cuesheet->is_last = false;
528 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
529 cuesheet->data.cue_sheet.lead_in = 123;
530 cuesheet->data.cue_sheet.is_cd = false;
531 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
532 return die_("priming our metadata");
533 cuesheet->data.cue_sheet.tracks[0].number = 1;
534 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
535 return die_("priming our metadata");
538 padding.is_last = true;
539 padding.type = FLAC__METADATA_TYPE_PADDING;
540 padding.length = 1234;
542 metadata[n++] = &vorbiscomment;
543 if (include_cuesheet)
544 metadata[n++] = cuesheet;
545 metadata[n++] = &padding;
548 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
549 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
550 (include_cuesheet && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
551 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
553 return die_("priming our metadata");
555 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
556 return die_("creating the encoded file");
558 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
563 static FLAC__bool test_file_(const char *filename, FLAC__StreamDecoderMetadataCallback metadata_callback)
565 FLAC__StreamDecoder *decoder;
566 decoder_client_struct decoder_client_data;
568 FLAC__ASSERT(0 != filename);
569 FLAC__ASSERT(0 != metadata_callback);
571 mc_our_block_number_ = 0;
572 decoder_client_data.error_occurred = false;
574 printf("\ttesting '%s'... ", filename);
577 if(0 == (decoder = FLAC__stream_decoder_new()))
578 return die_("couldn't allocate decoder instance");
580 FLAC__stream_decoder_set_md5_checking(decoder, true);
581 FLAC__stream_decoder_set_metadata_respond_all(decoder);
582 if(FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
583 FLAC__stream_decoder_finish(decoder);
584 FLAC__stream_decoder_delete(decoder);
585 return die_("initializing decoder\n");
587 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
588 FLAC__stream_decoder_finish(decoder);
589 FLAC__stream_decoder_delete(decoder);
590 return die_("decoding file\n");
593 FLAC__stream_decoder_finish(decoder);
594 FLAC__stream_decoder_delete(decoder);
596 if(decoder_client_data.error_occurred)
599 if(mc_our_block_number_ != our_metadata_.num_blocks)
600 return die_("short metadata block count");
606 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
608 if(!grabbag__file_change_stats(filename, read_only))
609 return die_("during grabbag__file_change_stats()");
614 static FLAC__bool remove_file_(const char *filename)
616 while(our_metadata_.num_blocks > 0)
617 delete_from_our_metadata_(0);
619 if(!grabbag__file_remove_file(filename))
620 return die_("removing file");
625 static FLAC__bool test_level_0_()
627 FLAC__StreamMetadata streaminfo;
628 FLAC__StreamMetadata *tags = 0;
629 FLAC__StreamMetadata *cuesheet = 0;
631 printf("\n\n++++++ testing level 0 interface\n");
633 if(!generate_file_(/*include_cuesheet=*/true))
636 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
639 printf("testing FLAC__metadata_get_streaminfo()... ");
641 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
642 return die_("during FLAC__metadata_get_streaminfo()");
644 /* check to see if some basic data matches (c.f. generate_file_()) */
645 if(streaminfo.data.stream_info.channels != 1)
646 return die_("mismatch in streaminfo.data.stream_info.channels");
647 if(streaminfo.data.stream_info.bits_per_sample != 8)
648 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
649 if(streaminfo.data.stream_info.sample_rate != 44100)
650 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
651 if(streaminfo.data.stream_info.min_blocksize != 576)
652 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
653 if(streaminfo.data.stream_info.max_blocksize != 576)
654 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
658 printf("testing FLAC__metadata_get_tags()... ");
660 if(!FLAC__metadata_get_tags(flacfile_, &tags))
661 return die_("during FLAC__metadata_get_tags()");
663 /* check to see if some basic data matches (c.f. generate_file_()) */
664 if(tags->data.vorbis_comment.num_comments != 0)
665 return die_("mismatch in tags->data.vorbis_comment.num_comments");
669 FLAC__metadata_object_delete(tags);
671 printf("testing FLAC__metadata_get_cuesheet()... ");
673 if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
674 return die_("during FLAC__metadata_get_cuesheet()");
676 /* check to see if some basic data matches (c.f. generate_file_()) */
677 if(cuesheet->data.cue_sheet.lead_in != 123)
678 return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
682 FLAC__metadata_object_delete(cuesheet);
684 if(!remove_file_(flacfile_))
690 static FLAC__bool test_level_1_()
692 FLAC__Metadata_SimpleIterator *iterator;
693 FLAC__StreamMetadata *block, *app, *padding;
694 FLAC__byte data[1000];
695 unsigned our_current_position = 0;
697 /* initialize 'data' to avoid Valgrind errors */
698 memset(data, 0, sizeof(data));
700 printf("\n\n++++++ testing level 1 interface\n");
702 /************************************************************/
704 printf("simple iterator on read-only file\n");
706 if(!generate_file_(/*include_cuesheet=*/false))
709 if(!change_stats_(flacfile_, /*read_only=*/true))
712 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
715 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
716 return die_("FLAC__metadata_simple_iterator_new()");
718 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
719 return die_("FLAC__metadata_simple_iterator_init() returned false");
721 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
722 if(FLAC__metadata_simple_iterator_is_writable(iterator))
723 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
725 printf("iterate forwards\n");
727 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
728 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
729 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
730 return die_("getting block 0");
731 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
732 return die_("expected STREAMINFO type");
734 return die_("expected is_last to be false");
735 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
736 return die_("bad STREAMINFO length");
737 /* check to see if some basic data matches (c.f. generate_file_()) */
738 if(block->data.stream_info.channels != 1)
739 return die_("mismatch in channels");
740 if(block->data.stream_info.bits_per_sample != 8)
741 return die_("mismatch in bits_per_sample");
742 if(block->data.stream_info.sample_rate != 44100)
743 return die_("mismatch in sample_rate");
744 if(block->data.stream_info.min_blocksize != 576)
745 return die_("mismatch in min_blocksize");
746 if(block->data.stream_info.max_blocksize != 576)
747 return die_("mismatch in max_blocksize");
748 FLAC__metadata_object_delete(block);
750 if(!FLAC__metadata_simple_iterator_next(iterator))
751 return die_("forward iterator ended early");
752 our_current_position++;
754 if(!FLAC__metadata_simple_iterator_next(iterator))
755 return die_("forward iterator ended early");
756 our_current_position++;
758 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
759 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
760 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
761 return die_("getting block 2");
762 if(block->type != FLAC__METADATA_TYPE_PADDING)
763 return die_("expected PADDING type");
765 return die_("expected is_last to be true");
766 /* check to see if some basic data matches (c.f. generate_file_()) */
767 if(block->length != 1234)
768 return die_("bad PADDING length");
769 FLAC__metadata_object_delete(block);
771 if(FLAC__metadata_simple_iterator_next(iterator))
772 return die_("forward iterator returned true but should have returned false");
774 printf("iterate backwards\n");
775 if(!FLAC__metadata_simple_iterator_prev(iterator))
776 return die_("reverse iterator ended early");
777 if(!FLAC__metadata_simple_iterator_prev(iterator))
778 return die_("reverse iterator ended early");
779 if(FLAC__metadata_simple_iterator_prev(iterator))
780 return die_("reverse iterator returned true but should have returned false");
782 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
784 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
785 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
787 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
789 FLAC__metadata_simple_iterator_delete(iterator);
791 /************************************************************/
793 printf("simple iterator on writable file\n");
795 if(!change_stats_(flacfile_, /*read-only=*/false))
798 printf("creating APPLICATION block\n");
800 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
801 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
802 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
804 printf("creating PADDING block\n");
806 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
807 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
808 padding->length = 20;
810 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
811 return die_("FLAC__metadata_simple_iterator_new()");
813 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
814 return die_("FLAC__metadata_simple_iterator_init() returned false");
815 our_current_position = 0;
817 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
819 printf("[S]VP\ttry to write over STREAMINFO block...\n");
820 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
821 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
823 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
825 printf("[S]VP\tnext\n");
826 if(!FLAC__metadata_simple_iterator_next(iterator))
827 return die_("iterator ended early\n");
828 our_current_position++;
830 printf("S[V]P\tnext\n");
831 if(!FLAC__metadata_simple_iterator_next(iterator))
832 return die_("iterator ended early\n");
833 our_current_position++;
835 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
836 padding->length = 25;
837 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
838 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
839 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
842 printf("SVP[P]\tprev\n");
843 if(!FLAC__metadata_simple_iterator_prev(iterator))
844 return die_("iterator ended early\n");
845 our_current_position--;
847 printf("SV[P]P\tprev\n");
848 if(!FLAC__metadata_simple_iterator_prev(iterator))
849 return die_("iterator ended early\n");
850 our_current_position--;
852 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
853 padding->length = 30;
854 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
855 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
856 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
859 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
862 printf("SV[P]PP\tprev\n");
863 if(!FLAC__metadata_simple_iterator_prev(iterator))
864 return die_("iterator ended early\n");
865 our_current_position--;
867 printf("S[V]PPP\tprev\n");
868 if(!FLAC__metadata_simple_iterator_prev(iterator))
869 return die_("iterator ended early\n");
870 our_current_position--;
872 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
873 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
874 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
876 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
879 printf("[S]VPPP\tnext\n");
880 if(!FLAC__metadata_simple_iterator_next(iterator))
881 return die_("iterator ended early\n");
882 our_current_position++;
884 printf("S[V]PPP\tnext\n");
885 if(!FLAC__metadata_simple_iterator_next(iterator))
886 return die_("iterator ended early\n");
887 our_current_position++;
889 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
890 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
891 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
892 our_current_position--;
894 printf("S[V]PPP\tnext\n");
895 if(!FLAC__metadata_simple_iterator_next(iterator))
896 return die_("iterator ended early\n");
897 our_current_position++;
899 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
900 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
901 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
902 delete_from_our_metadata_(our_current_position--);
904 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
907 printf("S[V]PP\tnext\n");
908 if(!FLAC__metadata_simple_iterator_next(iterator))
909 return die_("iterator ended early\n");
910 our_current_position++;
912 printf("SV[P]P\tnext\n");
913 if(!FLAC__metadata_simple_iterator_next(iterator))
914 return die_("iterator ended early\n");
915 our_current_position++;
917 printf("SVP[P]\tdelete (last block), replace with padding\n");
918 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
919 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
920 our_current_position--;
922 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
925 printf("SV[P]P\tnext\n");
926 if(!FLAC__metadata_simple_iterator_next(iterator))
927 return die_("iterator ended early\n");
928 our_current_position++;
930 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
931 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
932 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
933 delete_from_our_metadata_(our_current_position--);
935 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
938 printf("SV[P]\tprev\n");
939 if(!FLAC__metadata_simple_iterator_prev(iterator))
940 return die_("iterator ended early\n");
941 our_current_position--;
943 printf("S[V]P\tprev\n");
944 if(!FLAC__metadata_simple_iterator_prev(iterator))
945 return die_("iterator ended early\n");
946 our_current_position--;
948 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
949 FLAC__ASSERT(our_current_position == 0);
950 block = FLAC__metadata_simple_iterator_get_block(iterator);
951 block->data.stream_info.sample_rate = 32000;
952 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
953 return die_("copying object");
954 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
955 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
956 FLAC__metadata_object_delete(block);
958 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
961 printf("[S]VP\tnext\n");
962 if(!FLAC__metadata_simple_iterator_next(iterator))
963 return die_("iterator ended early\n");
964 our_current_position++;
966 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
967 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
968 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
969 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
970 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
972 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
974 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
977 printf("SV[A]P\tnext\n");
978 if(!FLAC__metadata_simple_iterator_next(iterator))
979 return die_("iterator ended early\n");
980 our_current_position++;
982 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
983 app->data.application.id[0] = 'f'; /* twiddle the id */
984 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
985 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
986 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
988 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
990 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
993 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
994 app->data.application.id[0] = 'g'; /* twiddle the id */
995 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
996 return die_("setting APPLICATION data");
997 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
998 return die_("copying object");
999 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1000 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1002 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1005 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1006 app->data.application.id[0] = 'h'; /* twiddle the id */
1007 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1008 return die_("setting APPLICATION data");
1009 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1010 return die_("copying object");
1011 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1012 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1014 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1017 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1018 app->data.application.id[0] = 'i'; /* twiddle the id */
1019 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1020 return die_("setting APPLICATION data");
1021 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1022 return die_("copying object");
1023 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1024 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1025 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1027 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1030 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1031 app->data.application.id[0] = 'j'; /* twiddle the id */
1032 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1033 return die_("setting APPLICATION data");
1034 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1035 return die_("copying object");
1036 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1037 return die_("copying object");
1038 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1039 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1040 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1042 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1045 printf("SVA[A]PP\tnext\n");
1046 if(!FLAC__metadata_simple_iterator_next(iterator))
1047 return die_("iterator ended early\n");
1048 our_current_position++;
1050 printf("SVAA[P]P\tnext\n");
1051 if(!FLAC__metadata_simple_iterator_next(iterator))
1052 return die_("iterator ended early\n");
1053 our_current_position++;
1055 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1056 padding->length = 5;
1057 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1058 return die_("copying object");
1059 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1060 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1062 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1065 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1066 app->data.application.id[0] = 'k'; /* twiddle the id */
1067 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1068 return die_("copying object");
1069 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1070 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1072 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1075 printf("SVAAP[A]\tset PADDING (equal)\n");
1076 padding->length = 27;
1077 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1078 return die_("copying object");
1079 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1080 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1082 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1085 printf("SVAAP[P]\tprev\n");
1086 if(!FLAC__metadata_simple_iterator_prev(iterator))
1087 return die_("iterator ended early\n");
1088 our_current_position--;
1090 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1091 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1092 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1093 delete_from_our_metadata_(our_current_position--);
1095 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1098 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1099 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1100 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1101 delete_from_our_metadata_(our_current_position--);
1103 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1106 printf("SV[A]P\tnext\n");
1107 if(!FLAC__metadata_simple_iterator_next(iterator))
1108 return die_("iterator ended early\n");
1109 our_current_position++;
1111 printf("SVA[P]\tinsert PADDING after\n");
1112 padding->length = 5;
1113 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1114 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1115 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1118 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1121 printf("SVAP[P]\tprev\n");
1122 if(!FLAC__metadata_simple_iterator_prev(iterator))
1123 return die_("iterator ended early\n");
1124 our_current_position--;
1126 printf("SVA[P]P\tprev\n");
1127 if(!FLAC__metadata_simple_iterator_prev(iterator))
1128 return die_("iterator ended early\n");
1129 our_current_position--;
1131 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1132 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1133 return die_("setting APPLICATION data");
1134 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1135 return die_("copying object");
1136 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1137 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1139 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1142 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1143 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1144 return die_("setting APPLICATION data");
1145 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1146 return die_("copying object");
1147 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1148 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1150 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1153 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1154 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1155 return die_("setting APPLICATION data");
1156 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1157 return die_("copying object");
1158 our_metadata_.blocks[our_current_position+1]->length = 0;
1159 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1160 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1162 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1165 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1166 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1167 return die_("setting APPLICATION data");
1168 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1169 return die_("copying object");
1170 delete_from_our_metadata_(our_current_position+1);
1171 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1172 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1174 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1177 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1178 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1179 return die_("setting APPLICATION data");
1180 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1181 return die_("copying object");
1182 delete_from_our_metadata_(our_current_position+1);
1183 our_metadata_.blocks[our_current_position]->is_last = true;
1184 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1185 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1187 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1190 printf("SV[A]\tset PADDING (equal size)\n");
1191 padding->length = app->length;
1192 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1193 return die_("copying object");
1194 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1195 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1197 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1200 printf("SV[P]\tinsert PADDING after\n");
1201 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1202 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1203 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1206 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1209 printf("SVP[P]\tinsert PADDING after\n");
1210 padding->length = 5;
1211 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1212 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1213 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1216 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1219 printf("SVPP[P]\tprev\n");
1220 if(!FLAC__metadata_simple_iterator_prev(iterator))
1221 return die_("iterator ended early\n");
1222 our_current_position--;
1224 printf("SVP[P]P\tprev\n");
1225 if(!FLAC__metadata_simple_iterator_prev(iterator))
1226 return die_("iterator ended early\n");
1227 our_current_position--;
1229 printf("SV[P]PP\tprev\n");
1230 if(!FLAC__metadata_simple_iterator_prev(iterator))
1231 return die_("iterator ended early\n");
1232 our_current_position--;
1234 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1235 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1236 return die_("setting APPLICATION data");
1237 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1238 return die_("copying object");
1239 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1240 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1242 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1245 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1246 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1247 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1248 delete_from_our_metadata_(our_current_position--);
1250 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1253 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1254 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1255 return die_("setting APPLICATION data");
1256 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1257 return die_("copying object");
1258 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1259 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1261 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1264 printf("SV[A]PPP\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]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1273 if(!FLAC__metadata_object_application_set_data(app, data, 100, 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("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1285 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1286 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1287 delete_from_our_metadata_(our_current_position--);
1289 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1292 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1293 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1294 return die_("setting APPLICATION data");
1295 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1296 return die_("copying object");
1297 our_metadata_.blocks[our_current_position+1]->length = 0;
1298 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1299 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1301 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1304 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1305 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1306 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1307 delete_from_our_metadata_(our_current_position--);
1309 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1312 printf("S[V]PP\tnext\n");
1313 if(!FLAC__metadata_simple_iterator_next(iterator))
1314 return die_("iterator ended early\n");
1315 our_current_position++;
1317 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1318 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1319 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1320 delete_from_our_metadata_(our_current_position--);
1322 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1325 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1326 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1327 return die_("setting APPLICATION data");
1328 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1329 return die_("copying object");
1330 delete_from_our_metadata_(our_current_position+1);
1331 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1332 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1334 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1337 printf("delete simple iterator\n");
1339 FLAC__metadata_simple_iterator_delete(iterator);
1341 FLAC__metadata_object_delete(app);
1342 FLAC__metadata_object_delete(padding);
1344 if(!remove_file_(flacfile_))
1350 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1352 FLAC__Metadata_Iterator *iterator;
1353 FLAC__Metadata_Chain *chain;
1354 FLAC__StreamMetadata *block, *app, *padding;
1355 FLAC__byte data[2000];
1356 unsigned our_current_position;
1358 /* initialize 'data' to avoid Valgrind errors */
1359 memset(data, 0, sizeof(data));
1361 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1363 printf("generate read-only file\n");
1365 if(!generate_file_(/*include_cuesheet=*/false))
1368 if(!change_stats_(flacfile_, /*read_only=*/true))
1371 printf("create chain\n");
1373 if(0 == (chain = FLAC__metadata_chain_new()))
1374 return die_("allocating chain");
1376 printf("read chain\n");
1378 if(!read_chain_(chain, flacfile_, filename_based))
1379 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1381 printf("[S]VP\ttest initial metadata\n");
1383 if(!compare_chain_(chain, 0, 0))
1385 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1388 printf("switch file to read-write\n");
1390 if(!change_stats_(flacfile_, /*read-only=*/false))
1393 printf("create iterator\n");
1394 if(0 == (iterator = FLAC__metadata_iterator_new()))
1395 return die_("allocating memory for iterator");
1397 our_current_position = 0;
1399 FLAC__metadata_iterator_init(iterator, chain);
1401 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1402 return die_("getting block from iterator");
1404 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1406 printf("[S]VP\tmodify STREAMINFO, write\n");
1408 block->data.stream_info.sample_rate = 32000;
1409 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1410 return die_("copying object");
1412 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1413 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1414 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1416 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1419 printf("[S]VP\tnext\n");
1420 if(!FLAC__metadata_iterator_next(iterator))
1421 return die_("iterator ended early\n");
1422 our_current_position++;
1424 printf("S[V]P\tnext\n");
1425 if(!FLAC__metadata_iterator_next(iterator))
1426 return die_("iterator ended early\n");
1427 our_current_position++;
1429 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1430 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1431 return die_("getting block from iterator");
1432 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1433 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1434 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1435 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1436 return die_("setting APPLICATION data");
1437 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1438 return die_("copying object");
1439 if(!FLAC__metadata_iterator_set_block(iterator, app))
1440 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1442 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1443 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1444 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1446 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1449 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1450 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1451 return die_("copying object");
1452 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1453 return die_("setting APPLICATION data");
1454 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1455 return die_("copying object");
1456 if(!FLAC__metadata_iterator_set_block(iterator, app))
1457 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1459 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1460 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1461 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1463 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1466 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
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, 28, 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 if(!FLAC__metadata_iterator_set_block(iterator, app))
1474 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1476 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1477 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1478 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1480 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1483 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1484 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1485 return die_("copying object");
1486 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1487 return die_("setting APPLICATION data");
1488 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1489 return die_("copying object");
1490 if(!FLAC__metadata_iterator_set_block(iterator, app))
1491 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1493 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1494 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1495 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1497 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1500 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1501 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1502 return die_("copying object");
1503 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1504 return die_("setting APPLICATION data");
1505 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1506 return die_("copying object");
1507 if(!FLAC__metadata_iterator_set_block(iterator, app))
1508 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1510 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1511 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1512 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1514 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1517 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1518 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1519 return die_("creating PADDING block");
1520 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1521 return die_("copying object");
1522 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1523 return die_("setting APPLICATION data");
1524 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1525 return die_("copying object");
1526 padding->length = 0;
1527 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1528 return die_("internal error");
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\tshrink APPLICATION, use padding, last block is padding\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, 16, true))
1543 return die_("setting APPLICATION data");
1544 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1545 return die_("copying object");
1546 our_metadata_.blocks[our_current_position+1]->length = 13;
1547 if(!FLAC__metadata_iterator_set_block(iterator, app))
1548 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1550 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1551 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1552 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1554 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1557 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1558 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1559 return die_("copying object");
1560 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1561 return die_("setting APPLICATION data");
1562 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1563 return die_("copying object");
1564 if(!FLAC__metadata_iterator_set_block(iterator, app))
1565 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1567 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1568 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1569 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1571 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1574 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1575 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1576 return die_("copying object");
1577 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1578 return die_("setting APPLICATION data");
1579 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1580 return die_("copying object");
1581 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1582 if(!FLAC__metadata_iterator_set_block(iterator, app))
1583 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1585 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1586 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1587 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1589 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1592 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1593 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1594 return die_("copying object");
1595 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1596 return die_("setting APPLICATION data");
1597 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1598 return die_("copying object");
1599 delete_from_our_metadata_(our_current_position+1);
1600 if(!FLAC__metadata_iterator_set_block(iterator, app))
1601 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1603 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1604 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1605 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1607 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1610 printf("SV[A]\tprev\n");
1611 if(!FLAC__metadata_iterator_prev(iterator))
1612 return die_("iterator ended early\n");
1613 our_current_position--;
1615 printf("S[V]A\tprev\n");
1616 if(!FLAC__metadata_iterator_prev(iterator))
1617 return die_("iterator ended early\n");
1618 our_current_position--;
1620 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1621 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1622 return die_("creating PADDING block");
1623 padding->length = 30;
1624 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1625 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1627 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1629 printf("[S]VP\tnext\n");
1630 if(!FLAC__metadata_iterator_next(iterator))
1631 return die_("iterator ended early\n");
1632 our_current_position++;
1634 printf("S[V]A\tinsert PADDING after\n");
1635 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1636 return die_("copying metadata");
1637 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1638 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1640 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1643 printf("SV[P]A\tinsert PADDING before\n");
1644 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1645 return die_("creating PADDING block");
1646 padding->length = 17;
1647 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1648 return die_("copying metadata");
1649 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1650 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1652 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1655 printf("SV[P]PA\tinsert PADDING before\n");
1656 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1657 return die_("creating PADDING block");
1658 padding->length = 0;
1659 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1660 return die_("copying metadata");
1661 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1662 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1664 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1667 printf("SV[P]PPA\tnext\n");
1668 if(!FLAC__metadata_iterator_next(iterator))
1669 return die_("iterator ended early\n");
1670 our_current_position++;
1672 printf("SVP[P]PA\tnext\n");
1673 if(!FLAC__metadata_iterator_next(iterator))
1674 return die_("iterator ended early\n");
1675 our_current_position++;
1677 printf("SVPP[P]A\tnext\n");
1678 if(!FLAC__metadata_iterator_next(iterator))
1679 return die_("iterator ended early\n");
1680 our_current_position++;
1682 printf("SVPPP[A]\tinsert PADDING after\n");
1683 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1684 return die_("creating PADDING block");
1685 padding->length = 57;
1686 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1687 return die_("copying metadata");
1688 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1689 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1691 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1694 printf("SVPPPA[P]\tinsert PADDING before\n");
1695 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1696 return die_("creating PADDING block");
1697 padding->length = 99;
1698 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1699 return die_("copying metadata");
1700 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1701 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1703 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1706 printf("delete iterator\n");
1707 FLAC__metadata_iterator_delete(iterator);
1708 our_current_position = 0;
1710 printf("SVPPPAPP\tmerge padding\n");
1711 FLAC__metadata_chain_merge_padding(chain);
1712 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1713 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1714 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1715 delete_from_our_metadata_(7);
1716 delete_from_our_metadata_(4);
1717 delete_from_our_metadata_(3);
1719 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1720 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1721 if(!compare_chain_(chain, 0, 0))
1723 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1726 printf("SVPAP\tsort padding\n");
1727 FLAC__metadata_chain_sort_padding(chain);
1728 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1729 delete_from_our_metadata_(2);
1731 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1732 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1733 if(!compare_chain_(chain, 0, 0))
1735 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1738 printf("create iterator\n");
1739 if(0 == (iterator = FLAC__metadata_iterator_new()))
1740 return die_("allocating memory for iterator");
1742 our_current_position = 0;
1744 FLAC__metadata_iterator_init(iterator, chain);
1746 printf("[S]VAP\tnext\n");
1747 if(!FLAC__metadata_iterator_next(iterator))
1748 return die_("iterator ended early\n");
1749 our_current_position++;
1751 printf("S[V]AP\tnext\n");
1752 if(!FLAC__metadata_iterator_next(iterator))
1753 return die_("iterator ended early\n");
1754 our_current_position++;
1756 printf("SV[A]P\tdelete middle block, replace with padding\n");
1757 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1758 return die_("creating PADDING block");
1759 padding->length = 71;
1760 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1761 return die_("copying object");
1762 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1763 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1765 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1768 printf("S[V]PP\tnext\n");
1769 if(!FLAC__metadata_iterator_next(iterator))
1770 return die_("iterator ended early\n");
1771 our_current_position++;
1773 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1774 delete_from_our_metadata_(our_current_position--);
1775 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1776 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1778 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1781 printf("S[V]P\tnext\n");
1782 if(!FLAC__metadata_iterator_next(iterator))
1783 return die_("iterator ended early\n");
1784 our_current_position++;
1786 printf("SV[P]\tdelete last block, replace with padding\n");
1787 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1788 return die_("creating PADDING block");
1789 padding->length = 219;
1790 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1791 return die_("copying object");
1792 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1793 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1795 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1798 printf("S[V]P\tnext\n");
1799 if(!FLAC__metadata_iterator_next(iterator))
1800 return die_("iterator ended early\n");
1801 our_current_position++;
1803 printf("SV[P]\tdelete last block, don't replace with padding\n");
1804 delete_from_our_metadata_(our_current_position--);
1805 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1806 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1808 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1811 printf("S[V]\tprev\n");
1812 if(!FLAC__metadata_iterator_prev(iterator))
1813 return die_("iterator ended early\n");
1814 our_current_position--;
1816 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1817 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1818 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1820 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1823 printf("delete iterator\n");
1824 FLAC__metadata_iterator_delete(iterator);
1825 our_current_position = 0;
1827 printf("SV\tmerge padding\n");
1828 FLAC__metadata_chain_merge_padding(chain);
1830 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1831 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1832 if(!compare_chain_(chain, 0, 0))
1834 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1837 printf("SV\tsort padding\n");
1838 FLAC__metadata_chain_sort_padding(chain);
1840 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1841 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1842 if(!compare_chain_(chain, 0, 0))
1844 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1847 printf("delete chain\n");
1849 FLAC__metadata_chain_delete(chain);
1851 if(!remove_file_(flacfile_))
1857 static FLAC__bool test_level_2_misc_()
1859 FLAC__Metadata_Iterator *iterator;
1860 FLAC__Metadata_Chain *chain;
1861 FLAC__IOCallbacks callbacks;
1863 memset(&callbacks, 0, sizeof(callbacks));
1864 callbacks.read = (FLAC__IOCallback_Read)fread;
1865 #ifdef FLAC__VALGRIND_TESTING
1866 callbacks.write = chain_write_cb_;
1868 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1870 callbacks.seek = chain_seek_cb_;
1871 callbacks.tell = chain_tell_cb_;
1872 callbacks.eof = chain_eof_cb_;
1874 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1876 printf("generate file\n");
1878 if(!generate_file_(/*include_cuesheet=*/false))
1881 printf("create chain\n");
1883 if(0 == (chain = FLAC__metadata_chain_new()))
1884 return die_("allocating chain");
1886 printf("read chain (filename-based)\n");
1888 if(!FLAC__metadata_chain_read(chain, flacfile_))
1889 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1891 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1893 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1894 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1895 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1896 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1897 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1900 printf("read chain (filename-based)\n");
1902 if(!FLAC__metadata_chain_read(chain, flacfile_))
1903 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1905 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1907 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1908 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1909 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1910 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1911 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1914 printf("read chain (callback-based)\n");
1916 FILE *file = fopen(flacfile_, "rb");
1918 return die_("opening file");
1919 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1921 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1926 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1928 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1929 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1930 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1931 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1932 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1935 printf("read chain (callback-based)\n");
1937 FILE *file = fopen(flacfile_, "rb");
1939 return die_("opening file");
1940 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1942 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1947 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1949 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1950 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1952 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1954 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1956 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1957 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1958 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1959 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1960 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1963 printf("read chain (callback-based)\n");
1965 FILE *file = fopen(flacfile_, "rb");
1967 return die_("opening file");
1968 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1970 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1975 printf("create iterator\n");
1976 if(0 == (iterator = FLAC__metadata_iterator_new()))
1977 return die_("allocating memory for iterator");
1979 FLAC__metadata_iterator_init(iterator, chain);
1981 printf("[S]VP\tnext\n");
1982 if(!FLAC__metadata_iterator_next(iterator))
1983 return die_("iterator ended early\n");
1985 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1986 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1987 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1989 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1991 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1992 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1994 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
1996 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1998 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1999 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2000 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2001 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2002 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2005 printf("delete iterator\n");
2007 FLAC__metadata_iterator_delete(iterator);
2009 printf("delete chain\n");
2011 FLAC__metadata_chain_delete(chain);
2013 if(!remove_file_(flacfile_))
2019 FLAC__bool test_metadata_file_manipulation()
2021 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2023 our_metadata_.num_blocks = 0;
2025 if(!test_level_0_())
2028 if(!test_level_1_())
2031 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2033 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2035 if(!test_level_2_misc_())