1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002,2003,2004,2005 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__ || defined __EMX__
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__ && !defined __EMX__
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_(FLAC__bool include_cuesheet)
483 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
484 FLAC__StreamMetadata *metadata[3];
485 unsigned i = 0, n = 0;
487 printf("generating FLAC file for test\n");
489 while(our_metadata_.num_blocks > 0)
490 delete_from_our_metadata_(0);
492 streaminfo.is_last = false;
493 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
494 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
495 streaminfo.data.stream_info.min_blocksize = 576;
496 streaminfo.data.stream_info.max_blocksize = 576;
497 streaminfo.data.stream_info.min_framesize = 0;
498 streaminfo.data.stream_info.max_framesize = 0;
499 streaminfo.data.stream_info.sample_rate = 44100;
500 streaminfo.data.stream_info.channels = 1;
501 streaminfo.data.stream_info.bits_per_sample = 8;
502 streaminfo.data.stream_info.total_samples = 0;
503 memset(streaminfo.data.stream_info.md5sum, 0, 16);
506 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
507 vorbiscomment.is_last = false;
508 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
509 vorbiscomment.length = (4 + vendor_string_length) + 4;
510 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
511 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
512 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
513 vorbiscomment.data.vorbis_comment.num_comments = 0;
514 vorbiscomment.data.vorbis_comment.comments = 0;
518 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
519 return die_("priming our metadata");
520 cuesheet->is_last = false;
521 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
522 cuesheet->data.cue_sheet.lead_in = 123;
523 cuesheet->data.cue_sheet.is_cd = false;
524 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
525 return die_("priming our metadata");
526 cuesheet->data.cue_sheet.tracks[0].number = 1;
527 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
528 return die_("priming our metadata");
531 padding.is_last = true;
532 padding.type = FLAC__METADATA_TYPE_PADDING;
533 padding.length = 1234;
535 metadata[n++] = &vorbiscomment;
536 if (include_cuesheet)
537 metadata[n++] = cuesheet;
538 metadata[n++] = &padding;
541 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
542 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
543 (include_cuesheet && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
544 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
546 return die_("priming our metadata");
548 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
549 return die_("creating the encoded file");
551 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
556 static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
558 FLAC__FileDecoder *decoder;
559 decoder_client_struct decoder_client_data;
561 FLAC__ASSERT(0 != filename);
562 FLAC__ASSERT(0 != metadata_callback);
564 mc_our_block_number_ = 0;
565 decoder_client_data.error_occurred = false;
567 printf("\ttesting '%s'... ", filename);
570 if(0 == (decoder = FLAC__file_decoder_new()))
571 return die_("couldn't allocate decoder instance");
573 FLAC__file_decoder_set_md5_checking(decoder, true);
574 FLAC__file_decoder_set_filename(decoder, filename);
575 FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
576 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
577 FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
578 FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
579 FLAC__file_decoder_set_metadata_respond_all(decoder);
580 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
581 FLAC__file_decoder_finish(decoder);
582 FLAC__file_decoder_delete(decoder);
583 return die_("initializing decoder\n");
585 if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
586 FLAC__file_decoder_finish(decoder);
587 FLAC__file_decoder_delete(decoder);
588 return die_("decoding file\n");
591 FLAC__file_decoder_finish(decoder);
592 FLAC__file_decoder_delete(decoder);
594 if(decoder_client_data.error_occurred)
597 if(mc_our_block_number_ != our_metadata_.num_blocks)
598 return die_("short metadata block count");
604 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
606 if(!grabbag__file_change_stats(filename, read_only))
607 return die_("during grabbag__file_change_stats()");
612 static FLAC__bool remove_file_(const char *filename)
614 while(our_metadata_.num_blocks > 0)
615 delete_from_our_metadata_(0);
617 if(!grabbag__file_remove_file(filename))
618 return die_("removing file");
623 static FLAC__bool test_level_0_()
625 FLAC__StreamMetadata streaminfo;
626 FLAC__StreamMetadata *tags = 0;
627 FLAC__StreamMetadata *cuesheet = 0;
629 printf("\n\n++++++ testing level 0 interface\n");
631 if(!generate_file_(/*include_cuesheet=*/true))
634 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
637 printf("testing FLAC__metadata_get_streaminfo()... ");
639 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
640 return die_("during FLAC__metadata_get_streaminfo()");
642 /* check to see if some basic data matches (c.f. generate_file_()) */
643 if(streaminfo.data.stream_info.channels != 1)
644 return die_("mismatch in streaminfo.data.stream_info.channels");
645 if(streaminfo.data.stream_info.bits_per_sample != 8)
646 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
647 if(streaminfo.data.stream_info.sample_rate != 44100)
648 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
649 if(streaminfo.data.stream_info.min_blocksize != 576)
650 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
651 if(streaminfo.data.stream_info.max_blocksize != 576)
652 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
656 printf("testing FLAC__metadata_get_tags()... ");
658 if(!FLAC__metadata_get_tags(flacfile_, &tags))
659 return die_("during FLAC__metadata_get_tags()");
661 /* check to see if some basic data matches (c.f. generate_file_()) */
662 if(tags->data.vorbis_comment.num_comments != 0)
663 return die_("mismatch in tags->data.vorbis_comment.num_comments");
667 FLAC__metadata_object_delete(tags);
669 printf("testing FLAC__metadata_get_cuesheet()... ");
671 if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
672 return die_("during FLAC__metadata_get_cuesheet()");
674 /* check to see if some basic data matches (c.f. generate_file_()) */
675 if(cuesheet->data.cue_sheet.lead_in != 123)
676 return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
680 FLAC__metadata_object_delete(cuesheet);
682 if(!remove_file_(flacfile_))
688 static FLAC__bool test_level_1_()
690 FLAC__Metadata_SimpleIterator *iterator;
691 FLAC__StreamMetadata *block, *app, *padding;
692 FLAC__byte data[1000];
693 unsigned our_current_position = 0;
695 /* initialize 'data' to avoid Valgrind errors */
696 memset(data, 0, sizeof(data));
698 printf("\n\n++++++ testing level 1 interface\n");
700 /************************************************************/
702 printf("simple iterator on read-only file\n");
704 if(!generate_file_(/*include_cuesheet=*/false))
707 if(!change_stats_(flacfile_, /*read_only=*/true))
710 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
713 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
714 return die_("FLAC__metadata_simple_iterator_new()");
716 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
717 return die_("FLAC__metadata_simple_iterator_init() returned false");
719 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
720 if(FLAC__metadata_simple_iterator_is_writable(iterator))
721 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
723 printf("iterate forwards\n");
725 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
726 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
727 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
728 return die_("getting block 0");
729 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
730 return die_("expected STREAMINFO type");
732 return die_("expected is_last to be false");
733 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
734 return die_("bad STREAMINFO length");
735 /* check to see if some basic data matches (c.f. generate_file_()) */
736 if(block->data.stream_info.channels != 1)
737 return die_("mismatch in channels");
738 if(block->data.stream_info.bits_per_sample != 8)
739 return die_("mismatch in bits_per_sample");
740 if(block->data.stream_info.sample_rate != 44100)
741 return die_("mismatch in sample_rate");
742 if(block->data.stream_info.min_blocksize != 576)
743 return die_("mismatch in min_blocksize");
744 if(block->data.stream_info.max_blocksize != 576)
745 return die_("mismatch in max_blocksize");
746 FLAC__metadata_object_delete(block);
748 if(!FLAC__metadata_simple_iterator_next(iterator))
749 return die_("forward iterator ended early");
750 our_current_position++;
752 if(!FLAC__metadata_simple_iterator_next(iterator))
753 return die_("forward iterator ended early");
754 our_current_position++;
756 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
757 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
758 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
759 return die_("getting block 2");
760 if(block->type != FLAC__METADATA_TYPE_PADDING)
761 return die_("expected PADDING type");
763 return die_("expected is_last to be true");
764 /* check to see if some basic data matches (c.f. generate_file_()) */
765 if(block->length != 1234)
766 return die_("bad PADDING length");
767 FLAC__metadata_object_delete(block);
769 if(FLAC__metadata_simple_iterator_next(iterator))
770 return die_("forward iterator returned true but should have returned false");
772 printf("iterate backwards\n");
773 if(!FLAC__metadata_simple_iterator_prev(iterator))
774 return die_("reverse iterator ended early");
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 returned true but should have returned false");
780 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
782 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
783 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
785 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
787 FLAC__metadata_simple_iterator_delete(iterator);
789 /************************************************************/
791 printf("simple iterator on writable file\n");
793 if(!change_stats_(flacfile_, /*read-only=*/false))
796 printf("creating APPLICATION block\n");
798 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
799 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
800 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
802 printf("creating PADDING block\n");
804 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
805 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
806 padding->length = 20;
808 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
809 return die_("FLAC__metadata_simple_iterator_new()");
811 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
812 return die_("FLAC__metadata_simple_iterator_init() returned false");
813 our_current_position = 0;
815 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
817 printf("[S]VP\ttry to write over STREAMINFO block...\n");
818 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
819 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
821 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
823 printf("[S]VP\tnext\n");
824 if(!FLAC__metadata_simple_iterator_next(iterator))
825 return die_("iterator ended early\n");
826 our_current_position++;
828 printf("S[V]P\tnext\n");
829 if(!FLAC__metadata_simple_iterator_next(iterator))
830 return die_("iterator ended early\n");
831 our_current_position++;
833 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
834 padding->length = 25;
835 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
836 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
837 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
840 printf("SVP[P]\tprev\n");
841 if(!FLAC__metadata_simple_iterator_prev(iterator))
842 return die_("iterator ended early\n");
843 our_current_position--;
845 printf("SV[P]P\tprev\n");
846 if(!FLAC__metadata_simple_iterator_prev(iterator))
847 return die_("iterator ended early\n");
848 our_current_position--;
850 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
851 padding->length = 30;
852 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
853 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
854 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
857 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
860 printf("SV[P]PP\tprev\n");
861 if(!FLAC__metadata_simple_iterator_prev(iterator))
862 return die_("iterator ended early\n");
863 our_current_position--;
865 printf("S[V]PPP\tprev\n");
866 if(!FLAC__metadata_simple_iterator_prev(iterator))
867 return die_("iterator ended early\n");
868 our_current_position--;
870 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
871 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
872 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
874 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
877 printf("[S]VPPP\tnext\n");
878 if(!FLAC__metadata_simple_iterator_next(iterator))
879 return die_("iterator ended early\n");
880 our_current_position++;
882 printf("S[V]PPP\tnext\n");
883 if(!FLAC__metadata_simple_iterator_next(iterator))
884 return die_("iterator ended early\n");
885 our_current_position++;
887 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
888 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
889 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
890 our_current_position--;
892 printf("S[V]PPP\tnext\n");
893 if(!FLAC__metadata_simple_iterator_next(iterator))
894 return die_("iterator ended early\n");
895 our_current_position++;
897 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
898 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
899 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
900 delete_from_our_metadata_(our_current_position--);
902 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
905 printf("S[V]PP\tnext\n");
906 if(!FLAC__metadata_simple_iterator_next(iterator))
907 return die_("iterator ended early\n");
908 our_current_position++;
910 printf("SV[P]P\tnext\n");
911 if(!FLAC__metadata_simple_iterator_next(iterator))
912 return die_("iterator ended early\n");
913 our_current_position++;
915 printf("SVP[P]\tdelete (last block), replace with padding\n");
916 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
917 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
918 our_current_position--;
920 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
923 printf("SV[P]P\tnext\n");
924 if(!FLAC__metadata_simple_iterator_next(iterator))
925 return die_("iterator ended early\n");
926 our_current_position++;
928 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
929 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
930 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
931 delete_from_our_metadata_(our_current_position--);
933 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
936 printf("SV[P]\tprev\n");
937 if(!FLAC__metadata_simple_iterator_prev(iterator))
938 return die_("iterator ended early\n");
939 our_current_position--;
941 printf("S[V]P\tprev\n");
942 if(!FLAC__metadata_simple_iterator_prev(iterator))
943 return die_("iterator ended early\n");
944 our_current_position--;
946 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
947 FLAC__ASSERT(our_current_position == 0);
948 block = FLAC__metadata_simple_iterator_get_block(iterator);
949 block->data.stream_info.sample_rate = 32000;
950 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
951 return die_("copying object");
952 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
953 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
954 FLAC__metadata_object_delete(block);
956 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
959 printf("[S]VP\tnext\n");
960 if(!FLAC__metadata_simple_iterator_next(iterator))
961 return die_("iterator ended early\n");
962 our_current_position++;
964 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
965 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
966 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
967 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
968 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
970 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
972 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
975 printf("SV[A]P\tnext\n");
976 if(!FLAC__metadata_simple_iterator_next(iterator))
977 return die_("iterator ended early\n");
978 our_current_position++;
980 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
981 app->data.application.id[0] = 'f'; /* twiddle the id */
982 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
983 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
984 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
986 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
988 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
991 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
992 app->data.application.id[0] = 'g'; /* twiddle the id */
993 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
994 return die_("setting APPLICATION data");
995 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
996 return die_("copying object");
997 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
998 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1000 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1003 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1004 app->data.application.id[0] = 'h'; /* twiddle the id */
1005 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1006 return die_("setting APPLICATION data");
1007 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1008 return die_("copying object");
1009 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1010 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1012 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1015 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1016 app->data.application.id[0] = 'i'; /* twiddle the id */
1017 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1018 return die_("setting APPLICATION data");
1019 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1020 return die_("copying object");
1021 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1022 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1023 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1025 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1028 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1029 app->data.application.id[0] = 'j'; /* twiddle the id */
1030 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1031 return die_("setting APPLICATION data");
1032 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1033 return die_("copying object");
1034 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1035 return die_("copying object");
1036 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1037 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1038 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1040 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1043 printf("SVA[A]PP\tnext\n");
1044 if(!FLAC__metadata_simple_iterator_next(iterator))
1045 return die_("iterator ended early\n");
1046 our_current_position++;
1048 printf("SVAA[P]P\tnext\n");
1049 if(!FLAC__metadata_simple_iterator_next(iterator))
1050 return die_("iterator ended early\n");
1051 our_current_position++;
1053 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1054 padding->length = 5;
1055 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1056 return die_("copying object");
1057 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1058 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1060 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1063 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1064 app->data.application.id[0] = 'k'; /* twiddle the id */
1065 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1066 return die_("copying object");
1067 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1068 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1070 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1073 printf("SVAAP[A]\tset PADDING (equal)\n");
1074 padding->length = 27;
1075 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1076 return die_("copying object");
1077 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1078 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1080 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1083 printf("SVAAP[P]\tprev\n");
1084 if(!FLAC__metadata_simple_iterator_prev(iterator))
1085 return die_("iterator ended early\n");
1086 our_current_position--;
1088 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1089 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1090 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1091 delete_from_our_metadata_(our_current_position--);
1093 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1096 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1097 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1098 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1099 delete_from_our_metadata_(our_current_position--);
1101 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1104 printf("SV[A]P\tnext\n");
1105 if(!FLAC__metadata_simple_iterator_next(iterator))
1106 return die_("iterator ended early\n");
1107 our_current_position++;
1109 printf("SVA[P]\tinsert PADDING after\n");
1110 padding->length = 5;
1111 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1112 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1113 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1116 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1119 printf("SVAP[P]\tprev\n");
1120 if(!FLAC__metadata_simple_iterator_prev(iterator))
1121 return die_("iterator ended early\n");
1122 our_current_position--;
1124 printf("SVA[P]P\tprev\n");
1125 if(!FLAC__metadata_simple_iterator_prev(iterator))
1126 return die_("iterator ended early\n");
1127 our_current_position--;
1129 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1130 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1131 return die_("setting APPLICATION data");
1132 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1133 return die_("copying object");
1134 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1135 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1137 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1140 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1141 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1142 return die_("setting APPLICATION data");
1143 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1144 return die_("copying object");
1145 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1146 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1148 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1151 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1152 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1153 return die_("setting APPLICATION data");
1154 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1155 return die_("copying object");
1156 our_metadata_.blocks[our_current_position+1]->length = 0;
1157 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1158 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1160 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1163 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1164 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1165 return die_("setting APPLICATION data");
1166 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1167 return die_("copying object");
1168 delete_from_our_metadata_(our_current_position+1);
1169 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1170 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1172 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1175 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1176 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1177 return die_("setting APPLICATION data");
1178 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1179 return die_("copying object");
1180 delete_from_our_metadata_(our_current_position+1);
1181 our_metadata_.blocks[our_current_position]->is_last = true;
1182 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1183 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1185 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1188 printf("SV[A]\tset PADDING (equal size)\n");
1189 padding->length = app->length;
1190 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1191 return die_("copying object");
1192 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1193 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1195 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1198 printf("SV[P]\tinsert PADDING after\n");
1199 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1200 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1201 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1204 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1207 printf("SVP[P]\tinsert PADDING after\n");
1208 padding->length = 5;
1209 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1210 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1211 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1214 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1217 printf("SVPP[P]\tprev\n");
1218 if(!FLAC__metadata_simple_iterator_prev(iterator))
1219 return die_("iterator ended early\n");
1220 our_current_position--;
1222 printf("SVP[P]P\tprev\n");
1223 if(!FLAC__metadata_simple_iterator_prev(iterator))
1224 return die_("iterator ended early\n");
1225 our_current_position--;
1227 printf("SV[P]PP\tprev\n");
1228 if(!FLAC__metadata_simple_iterator_prev(iterator))
1229 return die_("iterator ended early\n");
1230 our_current_position--;
1232 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1233 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1234 return die_("setting APPLICATION data");
1235 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1236 return die_("copying object");
1237 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1238 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1240 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1243 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1244 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1245 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1246 delete_from_our_metadata_(our_current_position--);
1248 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1251 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1252 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1253 return die_("setting APPLICATION data");
1254 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1255 return die_("copying object");
1256 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1257 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1259 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1262 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1263 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1264 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1265 delete_from_our_metadata_(our_current_position--);
1267 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1270 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1271 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1272 return die_("setting APPLICATION data");
1273 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1274 return die_("copying object");
1275 delete_from_our_metadata_(our_current_position+1);
1276 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1277 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1279 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1282 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1283 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1284 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1285 delete_from_our_metadata_(our_current_position--);
1287 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1290 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1291 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1292 return die_("setting APPLICATION data");
1293 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1294 return die_("copying object");
1295 our_metadata_.blocks[our_current_position+1]->length = 0;
1296 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1297 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1299 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1302 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1303 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1304 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1305 delete_from_our_metadata_(our_current_position--);
1307 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1310 printf("S[V]PP\tnext\n");
1311 if(!FLAC__metadata_simple_iterator_next(iterator))
1312 return die_("iterator ended early\n");
1313 our_current_position++;
1315 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1316 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1317 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1318 delete_from_our_metadata_(our_current_position--);
1320 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1323 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1324 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1325 return die_("setting APPLICATION data");
1326 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1327 return die_("copying object");
1328 delete_from_our_metadata_(our_current_position+1);
1329 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1330 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1332 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1335 printf("delete simple iterator\n");
1337 FLAC__metadata_simple_iterator_delete(iterator);
1339 FLAC__metadata_object_delete(app);
1340 FLAC__metadata_object_delete(padding);
1342 if(!remove_file_(flacfile_))
1348 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1350 FLAC__Metadata_Iterator *iterator;
1351 FLAC__Metadata_Chain *chain;
1352 FLAC__StreamMetadata *block, *app, *padding;
1353 FLAC__byte data[2000];
1354 unsigned our_current_position;
1356 /* initialize 'data' to avoid Valgrind errors */
1357 memset(data, 0, sizeof(data));
1359 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1361 printf("generate read-only file\n");
1363 if(!generate_file_(/*include_cuesheet=*/false))
1366 if(!change_stats_(flacfile_, /*read_only=*/true))
1369 printf("create chain\n");
1371 if(0 == (chain = FLAC__metadata_chain_new()))
1372 return die_("allocating chain");
1374 printf("read chain\n");
1376 if(!read_chain_(chain, flacfile_, filename_based))
1377 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1379 printf("[S]VP\ttest initial metadata\n");
1381 if(!compare_chain_(chain, 0, 0))
1383 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1386 printf("switch file to read-write\n");
1388 if(!change_stats_(flacfile_, /*read-only=*/false))
1391 printf("create iterator\n");
1392 if(0 == (iterator = FLAC__metadata_iterator_new()))
1393 return die_("allocating memory for iterator");
1395 our_current_position = 0;
1397 FLAC__metadata_iterator_init(iterator, chain);
1399 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1400 return die_("getting block from iterator");
1402 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1404 printf("[S]VP\tmodify STREAMINFO, write\n");
1406 block->data.stream_info.sample_rate = 32000;
1407 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1408 return die_("copying object");
1410 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1411 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1412 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1414 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1417 printf("[S]VP\tnext\n");
1418 if(!FLAC__metadata_iterator_next(iterator))
1419 return die_("iterator ended early\n");
1420 our_current_position++;
1422 printf("S[V]P\tnext\n");
1423 if(!FLAC__metadata_iterator_next(iterator))
1424 return die_("iterator ended early\n");
1425 our_current_position++;
1427 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1428 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1429 return die_("getting block from iterator");
1430 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1431 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1432 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1433 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), 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, don't use padding\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, 26, 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=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1458 return die_c_("during FLAC__metadata_chain_write(chain, false, 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]\tgrow APPLICATION, don't use padding\n");
1465 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1466 return die_("copying object");
1467 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1468 return die_("setting APPLICATION data");
1469 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1470 return die_("copying object");
1471 if(!FLAC__metadata_iterator_set_block(iterator, app))
1472 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1474 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1475 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1476 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1478 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1481 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1482 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1483 return die_("copying object");
1484 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1485 return die_("setting APPLICATION data");
1486 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1487 return die_("copying object");
1488 if(!FLAC__metadata_iterator_set_block(iterator, app))
1489 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1491 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1492 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1493 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1495 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1498 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1499 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1500 return die_("copying object");
1501 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1502 return die_("setting APPLICATION data");
1503 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1504 return die_("copying object");
1505 if(!FLAC__metadata_iterator_set_block(iterator, app))
1506 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1508 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1509 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1510 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1512 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1515 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1516 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1517 return die_("creating PADDING block");
1518 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1519 return die_("copying object");
1520 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1521 return die_("setting APPLICATION data");
1522 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1523 return die_("copying object");
1524 padding->length = 0;
1525 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1526 return die_("internal error");
1527 if(!FLAC__metadata_iterator_set_block(iterator, app))
1528 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1530 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1531 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1532 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1534 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1537 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1538 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1539 return die_("copying object");
1540 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1541 return die_("setting APPLICATION data");
1542 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1543 return die_("copying object");
1544 our_metadata_.blocks[our_current_position+1]->length = 13;
1545 if(!FLAC__metadata_iterator_set_block(iterator, app))
1546 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1548 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1549 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1550 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1552 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1555 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1556 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1557 return die_("copying object");
1558 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1559 return die_("setting APPLICATION data");
1560 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1561 return die_("copying object");
1562 if(!FLAC__metadata_iterator_set_block(iterator, app))
1563 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1565 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1566 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1567 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1569 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1572 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1573 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1574 return die_("copying object");
1575 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1576 return die_("setting APPLICATION data");
1577 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1578 return die_("copying object");
1579 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1580 if(!FLAC__metadata_iterator_set_block(iterator, app))
1581 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1583 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1584 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1585 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1587 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1590 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1591 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1592 return die_("copying object");
1593 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1594 return die_("setting APPLICATION data");
1595 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1596 return die_("copying object");
1597 delete_from_our_metadata_(our_current_position+1);
1598 if(!FLAC__metadata_iterator_set_block(iterator, app))
1599 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1601 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1602 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1603 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1605 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1608 printf("SV[A]\tprev\n");
1609 if(!FLAC__metadata_iterator_prev(iterator))
1610 return die_("iterator ended early\n");
1611 our_current_position--;
1613 printf("S[V]A\tprev\n");
1614 if(!FLAC__metadata_iterator_prev(iterator))
1615 return die_("iterator ended early\n");
1616 our_current_position--;
1618 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1619 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1620 return die_("creating PADDING block");
1621 padding->length = 30;
1622 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1623 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1625 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1627 printf("[S]VP\tnext\n");
1628 if(!FLAC__metadata_iterator_next(iterator))
1629 return die_("iterator ended early\n");
1630 our_current_position++;
1632 printf("S[V]A\tinsert PADDING after\n");
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("SV[P]A\tinsert PADDING before\n");
1642 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1643 return die_("creating PADDING block");
1644 padding->length = 17;
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("SV[P]PA\tinsert PADDING before\n");
1654 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1655 return die_("creating PADDING block");
1656 padding->length = 0;
1657 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1658 return die_("copying metadata");
1659 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1660 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1662 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1665 printf("SV[P]PPA\tnext\n");
1666 if(!FLAC__metadata_iterator_next(iterator))
1667 return die_("iterator ended early\n");
1668 our_current_position++;
1670 printf("SVP[P]PA\tnext\n");
1671 if(!FLAC__metadata_iterator_next(iterator))
1672 return die_("iterator ended early\n");
1673 our_current_position++;
1675 printf("SVPP[P]A\tnext\n");
1676 if(!FLAC__metadata_iterator_next(iterator))
1677 return die_("iterator ended early\n");
1678 our_current_position++;
1680 printf("SVPPP[A]\tinsert PADDING after\n");
1681 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1682 return die_("creating PADDING block");
1683 padding->length = 57;
1684 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1685 return die_("copying metadata");
1686 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1687 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1689 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1692 printf("SVPPPA[P]\tinsert PADDING before\n");
1693 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1694 return die_("creating PADDING block");
1695 padding->length = 99;
1696 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1697 return die_("copying metadata");
1698 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1699 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1701 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1704 printf("delete iterator\n");
1705 FLAC__metadata_iterator_delete(iterator);
1706 our_current_position = 0;
1708 printf("SVPPPAPP\tmerge padding\n");
1709 FLAC__metadata_chain_merge_padding(chain);
1710 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1711 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1712 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1713 delete_from_our_metadata_(7);
1714 delete_from_our_metadata_(4);
1715 delete_from_our_metadata_(3);
1717 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1718 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1719 if(!compare_chain_(chain, 0, 0))
1721 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1724 printf("SVPAP\tsort padding\n");
1725 FLAC__metadata_chain_sort_padding(chain);
1726 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1727 delete_from_our_metadata_(2);
1729 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1730 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1731 if(!compare_chain_(chain, 0, 0))
1733 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1736 printf("create iterator\n");
1737 if(0 == (iterator = FLAC__metadata_iterator_new()))
1738 return die_("allocating memory for iterator");
1740 our_current_position = 0;
1742 FLAC__metadata_iterator_init(iterator, chain);
1744 printf("[S]VAP\tnext\n");
1745 if(!FLAC__metadata_iterator_next(iterator))
1746 return die_("iterator ended early\n");
1747 our_current_position++;
1749 printf("S[V]AP\tnext\n");
1750 if(!FLAC__metadata_iterator_next(iterator))
1751 return die_("iterator ended early\n");
1752 our_current_position++;
1754 printf("SV[A]P\tdelete middle block, replace with padding\n");
1755 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1756 return die_("creating PADDING block");
1757 padding->length = 71;
1758 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1759 return die_("copying object");
1760 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1761 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1763 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1766 printf("S[V]PP\tnext\n");
1767 if(!FLAC__metadata_iterator_next(iterator))
1768 return die_("iterator ended early\n");
1769 our_current_position++;
1771 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1772 delete_from_our_metadata_(our_current_position--);
1773 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1774 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1776 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1779 printf("S[V]P\tnext\n");
1780 if(!FLAC__metadata_iterator_next(iterator))
1781 return die_("iterator ended early\n");
1782 our_current_position++;
1784 printf("SV[P]\tdelete last block, replace with padding\n");
1785 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1786 return die_("creating PADDING block");
1787 padding->length = 219;
1788 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1789 return die_("copying object");
1790 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1791 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1793 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1796 printf("S[V]P\tnext\n");
1797 if(!FLAC__metadata_iterator_next(iterator))
1798 return die_("iterator ended early\n");
1799 our_current_position++;
1801 printf("SV[P]\tdelete last block, don't replace with padding\n");
1802 delete_from_our_metadata_(our_current_position--);
1803 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1804 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1806 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1809 printf("S[V]\tprev\n");
1810 if(!FLAC__metadata_iterator_prev(iterator))
1811 return die_("iterator ended early\n");
1812 our_current_position--;
1814 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1815 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1816 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1818 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1821 printf("delete iterator\n");
1822 FLAC__metadata_iterator_delete(iterator);
1823 our_current_position = 0;
1825 printf("SV\tmerge padding\n");
1826 FLAC__metadata_chain_merge_padding(chain);
1828 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1829 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1830 if(!compare_chain_(chain, 0, 0))
1832 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1835 printf("SV\tsort padding\n");
1836 FLAC__metadata_chain_sort_padding(chain);
1838 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1839 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1840 if(!compare_chain_(chain, 0, 0))
1842 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1845 printf("delete chain\n");
1847 FLAC__metadata_chain_delete(chain);
1849 if(!remove_file_(flacfile_))
1855 static FLAC__bool test_level_2_misc_()
1857 FLAC__Metadata_Iterator *iterator;
1858 FLAC__Metadata_Chain *chain;
1859 FLAC__IOCallbacks callbacks;
1861 memset(&callbacks, 0, sizeof(callbacks));
1862 callbacks.read = (FLAC__IOCallback_Read)fread;
1863 #ifdef FLAC__VALGRIND_TESTING
1864 callbacks.write = chain_write_cb_;
1866 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1868 callbacks.seek = chain_seek_cb_;
1869 callbacks.tell = chain_tell_cb_;
1870 callbacks.eof = chain_eof_cb_;
1872 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1874 printf("generate file\n");
1876 if(!generate_file_(/*include_cuesheet=*/false))
1879 printf("create chain\n");
1881 if(0 == (chain = FLAC__metadata_chain_new()))
1882 return die_("allocating chain");
1884 printf("read chain (filename-based)\n");
1886 if(!FLAC__metadata_chain_read(chain, flacfile_))
1887 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1889 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1891 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1892 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1893 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1894 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1895 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1898 printf("read chain (filename-based)\n");
1900 if(!FLAC__metadata_chain_read(chain, flacfile_))
1901 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1903 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1905 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1906 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1907 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1908 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1909 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1912 printf("read chain (callback-based)\n");
1914 FILE *file = fopen(flacfile_, "rb");
1916 return die_("opening file");
1917 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1919 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1924 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1926 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1927 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1928 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1929 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1930 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1933 printf("read chain (callback-based)\n");
1935 FILE *file = fopen(flacfile_, "rb");
1937 return die_("opening file");
1938 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1940 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1945 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1947 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1948 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1950 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1952 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1954 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1955 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1956 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1957 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1958 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1961 printf("read chain (callback-based)\n");
1963 FILE *file = fopen(flacfile_, "rb");
1965 return die_("opening file");
1966 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1968 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1973 printf("create iterator\n");
1974 if(0 == (iterator = FLAC__metadata_iterator_new()))
1975 return die_("allocating memory for iterator");
1977 FLAC__metadata_iterator_init(iterator, chain);
1979 printf("[S]VP\tnext\n");
1980 if(!FLAC__metadata_iterator_next(iterator))
1981 return die_("iterator ended early\n");
1983 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1984 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1985 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1987 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1989 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1990 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1992 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
1994 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1996 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1997 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1998 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1999 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2000 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2003 printf("delete iterator\n");
2005 FLAC__metadata_iterator_delete(iterator);
2007 printf("delete chain\n");
2009 FLAC__metadata_chain_delete(chain);
2011 if(!remove_file_(flacfile_))
2017 FLAC__bool test_metadata_file_manipulation()
2019 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2021 our_metadata_.num_blocks = 0;
2023 if(!test_level_0_())
2026 if(!test_level_1_())
2029 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2031 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2033 if(!test_level_2_misc_())