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 if(unlink(filename) < 0) {
215 cleanup_tempfile_(tempfile, tempfilename);
220 if(0 != rename(*tempfilename, filename)) {
221 cleanup_tempfile_(tempfile, tempfilename);
225 cleanup_tempfile_(tempfile, tempfilename);
230 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
232 FLAC__ASSERT(0 != filename);
233 FLAC__ASSERT(0 != stats);
234 return (0 == stat(filename, stats));
237 void set_file_stats_(const char *filename, struct stat *stats)
239 struct utimbuf srctime;
241 FLAC__ASSERT(0 != filename);
242 FLAC__ASSERT(0 != stats);
244 srctime.actime = stats->st_atime;
245 srctime.modtime = stats->st_mtime;
246 (void)chmod(filename, stats->st_mode);
247 (void)utime(filename, &srctime);
248 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
249 (void)chown(filename, stats->st_uid, -1);
250 (void)chown(filename, -1, stats->st_gid);
254 #ifdef FLAC__VALGRIND_TESTING
255 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
257 FILE *stream = (FILE*)handle;
258 size_t ret = fwrite(ptr, size, nmemb, stream);
265 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
267 off_t o = (off_t)offset;
268 FLAC__ASSERT(offset == o);
269 return fseeko((FILE*)handle, o, whence);
272 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
274 return ftello((FILE*)handle);
277 static int chain_eof_cb_(FLAC__IOHandle handle)
279 return feof((FILE*)handle);
282 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)
285 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
287 FLAC__IOCallbacks callbacks;
289 memset(&callbacks, 0, sizeof(callbacks));
290 callbacks.read = (FLAC__IOCallback_Read)fread;
291 #ifdef FLAC__VALGRIND_TESTING
292 callbacks.write = chain_write_cb_;
294 callbacks.write = (FLAC__IOCallback_Write)fwrite;
296 callbacks.seek = chain_seek_cb_;
297 callbacks.eof = chain_eof_cb_;
299 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
301 FILE *file, *tempfile;
303 if(preserve_file_stats) {
304 if(!get_file_stats_(filename, &stats))
307 if(0 == (file = fopen(filename, "rb")))
308 return false; /*@@@ chain status still says OK though */
309 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
311 cleanup_tempfile_(&tempfile, &tempfilename);
312 return false; /*@@@ chain status still says OK though */
314 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
322 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
324 if(preserve_file_stats)
325 set_file_stats_(filename, &stats);
328 FILE *file = fopen(filename, "r+b");
330 return false; /*@@@ chain status still says OK though */
331 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
340 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
343 return FLAC__metadata_chain_read(chain, flacfile_);
345 FLAC__IOCallbacks callbacks;
347 memset(&callbacks, 0, sizeof(callbacks));
348 callbacks.read = (FLAC__IOCallback_Read)fread;
349 callbacks.seek = chain_seek_cb_;
350 callbacks.tell = chain_tell_cb_;
354 FILE *file = fopen(filename, "rb");
356 return false; /*@@@ chain status still says OK though */
357 ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
364 /* function for comparing our metadata to a FLAC__Metadata_Chain */
366 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
369 FLAC__Metadata_Iterator *iterator;
370 FLAC__StreamMetadata *block;
371 FLAC__bool next_ok = true;
373 FLAC__ASSERT(0 != chain);
375 printf("\tcomparing chain... ");
378 if(0 == (iterator = FLAC__metadata_iterator_new()))
379 return die_("allocating memory for iterator");
381 FLAC__metadata_iterator_init(iterator, chain);
388 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
389 FLAC__metadata_iterator_delete(iterator);
390 return die_("getting block from iterator");
393 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
394 FLAC__metadata_iterator_delete(iterator);
395 return die_("metadata block mismatch");
399 next_ok = FLAC__metadata_iterator_next(iterator);
400 } while(i < our_metadata_.num_blocks && next_ok);
402 FLAC__metadata_iterator_delete(iterator);
405 return die_("chain has more blocks than expected");
407 if(i < our_metadata_.num_blocks)
408 return die_("short block count in chain");
410 if(0 != current_block) {
411 printf("CURRENT_POSITION... ");
414 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
415 return die_("metadata block mismatch");
423 /* decoder callbacks for checking the file */
425 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
427 (void)decoder, (void)buffer, (void)client_data;
430 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
431 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
433 printf("content... ");
437 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
440 /* this version pays no attention to the metadata */
441 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
443 (void)decoder, (void)metadata, (void)client_data;
445 printf("%d... ", mc_our_block_number_);
448 mc_our_block_number_++;
451 /* this version is used when we want to compare to our metadata copy */
452 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
454 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
458 /* don't bother checking if we've already hit an error */
459 if(dcd->error_occurred)
462 printf("%d... ", mc_our_block_number_);
465 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
466 (void)die_("got more metadata blocks than expected");
467 dcd->error_occurred = true;
470 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
471 (void)die_("metadata block mismatch");
472 dcd->error_occurred = true;
475 mc_our_block_number_++;
478 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
480 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
483 dcd->error_occurred = true;
484 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
487 static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
489 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
490 FLAC__StreamMetadata *metadata[3];
491 unsigned i = 0, n = 0;
493 printf("generating FLAC file for test\n");
495 while(our_metadata_.num_blocks > 0)
496 delete_from_our_metadata_(0);
498 streaminfo.is_last = false;
499 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
500 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
501 streaminfo.data.stream_info.min_blocksize = 576;
502 streaminfo.data.stream_info.max_blocksize = 576;
503 streaminfo.data.stream_info.min_framesize = 0;
504 streaminfo.data.stream_info.max_framesize = 0;
505 streaminfo.data.stream_info.sample_rate = 44100;
506 streaminfo.data.stream_info.channels = 1;
507 streaminfo.data.stream_info.bits_per_sample = 8;
508 streaminfo.data.stream_info.total_samples = 0;
509 memset(streaminfo.data.stream_info.md5sum, 0, 16);
512 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
513 vorbiscomment.is_last = false;
514 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
515 vorbiscomment.length = (4 + vendor_string_length) + 4;
516 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
517 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
518 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
519 vorbiscomment.data.vorbis_comment.num_comments = 0;
520 vorbiscomment.data.vorbis_comment.comments = 0;
524 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
525 return die_("priming our metadata");
526 cuesheet->is_last = false;
527 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
528 cuesheet->data.cue_sheet.lead_in = 123;
529 cuesheet->data.cue_sheet.is_cd = false;
530 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
531 return die_("priming our metadata");
532 cuesheet->data.cue_sheet.tracks[0].number = 1;
533 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
534 return die_("priming our metadata");
537 padding.is_last = true;
538 padding.type = FLAC__METADATA_TYPE_PADDING;
539 padding.length = 1234;
541 metadata[n++] = &vorbiscomment;
542 if (include_cuesheet)
543 metadata[n++] = cuesheet;
544 metadata[n++] = &padding;
547 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
548 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
549 (include_cuesheet && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
550 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
552 return die_("priming our metadata");
554 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
555 return die_("creating the encoded file");
557 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
562 static FLAC__bool test_file_(const char *filename, FLAC__StreamDecoderMetadataCallback metadata_callback)
564 FLAC__StreamDecoder *decoder;
565 decoder_client_struct decoder_client_data;
567 FLAC__ASSERT(0 != filename);
568 FLAC__ASSERT(0 != metadata_callback);
570 mc_our_block_number_ = 0;
571 decoder_client_data.error_occurred = false;
573 printf("\ttesting '%s'... ", filename);
576 if(0 == (decoder = FLAC__stream_decoder_new()))
577 return die_("couldn't allocate decoder instance");
579 FLAC__stream_decoder_set_md5_checking(decoder, true);
580 FLAC__stream_decoder_set_metadata_respond_all(decoder);
581 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) {
582 FLAC__stream_decoder_finish(decoder);
583 FLAC__stream_decoder_delete(decoder);
584 return die_("initializing decoder\n");
586 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
587 FLAC__stream_decoder_finish(decoder);
588 FLAC__stream_decoder_delete(decoder);
589 return die_("decoding file\n");
592 FLAC__stream_decoder_finish(decoder);
593 FLAC__stream_decoder_delete(decoder);
595 if(decoder_client_data.error_occurred)
598 if(mc_our_block_number_ != our_metadata_.num_blocks)
599 return die_("short metadata block count");
605 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
607 if(!grabbag__file_change_stats(filename, read_only))
608 return die_("during grabbag__file_change_stats()");
613 static FLAC__bool remove_file_(const char *filename)
615 while(our_metadata_.num_blocks > 0)
616 delete_from_our_metadata_(0);
618 if(!grabbag__file_remove_file(filename))
619 return die_("removing file");
624 static FLAC__bool test_level_0_()
626 FLAC__StreamMetadata streaminfo;
627 FLAC__StreamMetadata *tags = 0;
628 FLAC__StreamMetadata *cuesheet = 0;
630 printf("\n\n++++++ testing level 0 interface\n");
632 if(!generate_file_(/*include_cuesheet=*/true))
635 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
638 printf("testing FLAC__metadata_get_streaminfo()... ");
640 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
641 return die_("during FLAC__metadata_get_streaminfo()");
643 /* check to see if some basic data matches (c.f. generate_file_()) */
644 if(streaminfo.data.stream_info.channels != 1)
645 return die_("mismatch in streaminfo.data.stream_info.channels");
646 if(streaminfo.data.stream_info.bits_per_sample != 8)
647 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
648 if(streaminfo.data.stream_info.sample_rate != 44100)
649 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
650 if(streaminfo.data.stream_info.min_blocksize != 576)
651 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
652 if(streaminfo.data.stream_info.max_blocksize != 576)
653 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
657 printf("testing FLAC__metadata_get_tags()... ");
659 if(!FLAC__metadata_get_tags(flacfile_, &tags))
660 return die_("during FLAC__metadata_get_tags()");
662 /* check to see if some basic data matches (c.f. generate_file_()) */
663 if(tags->data.vorbis_comment.num_comments != 0)
664 return die_("mismatch in tags->data.vorbis_comment.num_comments");
668 FLAC__metadata_object_delete(tags);
670 printf("testing FLAC__metadata_get_cuesheet()... ");
672 if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
673 return die_("during FLAC__metadata_get_cuesheet()");
675 /* check to see if some basic data matches (c.f. generate_file_()) */
676 if(cuesheet->data.cue_sheet.lead_in != 123)
677 return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
681 FLAC__metadata_object_delete(cuesheet);
683 if(!remove_file_(flacfile_))
689 static FLAC__bool test_level_1_()
691 FLAC__Metadata_SimpleIterator *iterator;
692 FLAC__StreamMetadata *block, *app, *padding;
693 FLAC__byte data[1000];
694 unsigned our_current_position = 0;
696 /* initialize 'data' to avoid Valgrind errors */
697 memset(data, 0, sizeof(data));
699 printf("\n\n++++++ testing level 1 interface\n");
701 /************************************************************/
703 printf("simple iterator on read-only file\n");
705 if(!generate_file_(/*include_cuesheet=*/false))
708 if(!change_stats_(flacfile_, /*read_only=*/true))
711 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
714 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
715 return die_("FLAC__metadata_simple_iterator_new()");
717 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
718 return die_("FLAC__metadata_simple_iterator_init() returned false");
720 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
721 if(FLAC__metadata_simple_iterator_is_writable(iterator))
722 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
724 printf("iterate forwards\n");
726 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
727 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
728 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
729 return die_("getting block 0");
730 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
731 return die_("expected STREAMINFO type");
733 return die_("expected is_last to be false");
734 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
735 return die_("bad STREAMINFO length");
736 /* check to see if some basic data matches (c.f. generate_file_()) */
737 if(block->data.stream_info.channels != 1)
738 return die_("mismatch in channels");
739 if(block->data.stream_info.bits_per_sample != 8)
740 return die_("mismatch in bits_per_sample");
741 if(block->data.stream_info.sample_rate != 44100)
742 return die_("mismatch in sample_rate");
743 if(block->data.stream_info.min_blocksize != 576)
744 return die_("mismatch in min_blocksize");
745 if(block->data.stream_info.max_blocksize != 576)
746 return die_("mismatch in max_blocksize");
747 FLAC__metadata_object_delete(block);
749 if(!FLAC__metadata_simple_iterator_next(iterator))
750 return die_("forward iterator ended early");
751 our_current_position++;
753 if(!FLAC__metadata_simple_iterator_next(iterator))
754 return die_("forward iterator ended early");
755 our_current_position++;
757 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
758 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
759 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
760 return die_("getting block 2");
761 if(block->type != FLAC__METADATA_TYPE_PADDING)
762 return die_("expected PADDING type");
764 return die_("expected is_last to be true");
765 /* check to see if some basic data matches (c.f. generate_file_()) */
766 if(block->length != 1234)
767 return die_("bad PADDING length");
768 FLAC__metadata_object_delete(block);
770 if(FLAC__metadata_simple_iterator_next(iterator))
771 return die_("forward iterator returned true but should have returned false");
773 printf("iterate backwards\n");
774 if(!FLAC__metadata_simple_iterator_prev(iterator))
775 return die_("reverse iterator ended early");
776 if(!FLAC__metadata_simple_iterator_prev(iterator))
777 return die_("reverse iterator ended early");
778 if(FLAC__metadata_simple_iterator_prev(iterator))
779 return die_("reverse iterator returned true but should have returned false");
781 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
783 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
784 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
786 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
788 FLAC__metadata_simple_iterator_delete(iterator);
790 /************************************************************/
792 printf("simple iterator on writable file\n");
794 if(!change_stats_(flacfile_, /*read-only=*/false))
797 printf("creating APPLICATION block\n");
799 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
800 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
801 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
803 printf("creating PADDING block\n");
805 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
806 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
807 padding->length = 20;
809 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
810 return die_("FLAC__metadata_simple_iterator_new()");
812 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
813 return die_("FLAC__metadata_simple_iterator_init() returned false");
814 our_current_position = 0;
816 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
818 printf("[S]VP\ttry to write over STREAMINFO block...\n");
819 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
820 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
822 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
824 printf("[S]VP\tnext\n");
825 if(!FLAC__metadata_simple_iterator_next(iterator))
826 return die_("iterator ended early\n");
827 our_current_position++;
829 printf("S[V]P\tnext\n");
830 if(!FLAC__metadata_simple_iterator_next(iterator))
831 return die_("iterator ended early\n");
832 our_current_position++;
834 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
835 padding->length = 25;
836 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
837 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
838 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
841 printf("SVP[P]\tprev\n");
842 if(!FLAC__metadata_simple_iterator_prev(iterator))
843 return die_("iterator ended early\n");
844 our_current_position--;
846 printf("SV[P]P\tprev\n");
847 if(!FLAC__metadata_simple_iterator_prev(iterator))
848 return die_("iterator ended early\n");
849 our_current_position--;
851 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
852 padding->length = 30;
853 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
854 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
855 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
858 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
861 printf("SV[P]PP\tprev\n");
862 if(!FLAC__metadata_simple_iterator_prev(iterator))
863 return die_("iterator ended early\n");
864 our_current_position--;
866 printf("S[V]PPP\tprev\n");
867 if(!FLAC__metadata_simple_iterator_prev(iterator))
868 return die_("iterator ended early\n");
869 our_current_position--;
871 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
872 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
873 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
875 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
878 printf("[S]VPPP\tnext\n");
879 if(!FLAC__metadata_simple_iterator_next(iterator))
880 return die_("iterator ended early\n");
881 our_current_position++;
883 printf("S[V]PPP\tnext\n");
884 if(!FLAC__metadata_simple_iterator_next(iterator))
885 return die_("iterator ended early\n");
886 our_current_position++;
888 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
889 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
890 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
891 our_current_position--;
893 printf("S[V]PPP\tnext\n");
894 if(!FLAC__metadata_simple_iterator_next(iterator))
895 return die_("iterator ended early\n");
896 our_current_position++;
898 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
899 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
900 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
901 delete_from_our_metadata_(our_current_position--);
903 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
906 printf("S[V]PP\tnext\n");
907 if(!FLAC__metadata_simple_iterator_next(iterator))
908 return die_("iterator ended early\n");
909 our_current_position++;
911 printf("SV[P]P\tnext\n");
912 if(!FLAC__metadata_simple_iterator_next(iterator))
913 return die_("iterator ended early\n");
914 our_current_position++;
916 printf("SVP[P]\tdelete (last block), replace with padding\n");
917 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
918 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
919 our_current_position--;
921 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
924 printf("SV[P]P\tnext\n");
925 if(!FLAC__metadata_simple_iterator_next(iterator))
926 return die_("iterator ended early\n");
927 our_current_position++;
929 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
930 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
931 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
932 delete_from_our_metadata_(our_current_position--);
934 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
937 printf("SV[P]\tprev\n");
938 if(!FLAC__metadata_simple_iterator_prev(iterator))
939 return die_("iterator ended early\n");
940 our_current_position--;
942 printf("S[V]P\tprev\n");
943 if(!FLAC__metadata_simple_iterator_prev(iterator))
944 return die_("iterator ended early\n");
945 our_current_position--;
947 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
948 FLAC__ASSERT(our_current_position == 0);
949 block = FLAC__metadata_simple_iterator_get_block(iterator);
950 block->data.stream_info.sample_rate = 32000;
951 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
952 return die_("copying object");
953 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
954 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
955 FLAC__metadata_object_delete(block);
957 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
960 printf("[S]VP\tnext\n");
961 if(!FLAC__metadata_simple_iterator_next(iterator))
962 return die_("iterator ended early\n");
963 our_current_position++;
965 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
966 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
967 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
968 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
969 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
971 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
973 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
976 printf("SV[A]P\tnext\n");
977 if(!FLAC__metadata_simple_iterator_next(iterator))
978 return die_("iterator ended early\n");
979 our_current_position++;
981 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
982 app->data.application.id[0] = 'f'; /* twiddle the id */
983 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
984 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
985 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
987 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
989 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
992 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
993 app->data.application.id[0] = 'g'; /* twiddle the id */
994 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
995 return die_("setting APPLICATION data");
996 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
997 return die_("copying object");
998 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
999 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1001 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1004 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1005 app->data.application.id[0] = 'h'; /* twiddle the id */
1006 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1007 return die_("setting APPLICATION data");
1008 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1009 return die_("copying object");
1010 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1011 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1013 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1016 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1017 app->data.application.id[0] = 'i'; /* twiddle the id */
1018 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1019 return die_("setting APPLICATION data");
1020 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1021 return die_("copying object");
1022 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1023 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1024 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1026 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1029 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1030 app->data.application.id[0] = 'j'; /* twiddle the id */
1031 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1032 return die_("setting APPLICATION data");
1033 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1034 return die_("copying object");
1035 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1036 return die_("copying object");
1037 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1038 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1039 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1041 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1044 printf("SVA[A]PP\tnext\n");
1045 if(!FLAC__metadata_simple_iterator_next(iterator))
1046 return die_("iterator ended early\n");
1047 our_current_position++;
1049 printf("SVAA[P]P\tnext\n");
1050 if(!FLAC__metadata_simple_iterator_next(iterator))
1051 return die_("iterator ended early\n");
1052 our_current_position++;
1054 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1055 padding->length = 5;
1056 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1057 return die_("copying object");
1058 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1059 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1061 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1064 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1065 app->data.application.id[0] = 'k'; /* twiddle the id */
1066 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1067 return die_("copying object");
1068 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1069 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1071 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1074 printf("SVAAP[A]\tset PADDING (equal)\n");
1075 padding->length = 27;
1076 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1077 return die_("copying object");
1078 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1079 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1081 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1084 printf("SVAAP[P]\tprev\n");
1085 if(!FLAC__metadata_simple_iterator_prev(iterator))
1086 return die_("iterator ended early\n");
1087 our_current_position--;
1089 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1090 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1091 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1092 delete_from_our_metadata_(our_current_position--);
1094 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1097 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1098 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1099 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1100 delete_from_our_metadata_(our_current_position--);
1102 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1105 printf("SV[A]P\tnext\n");
1106 if(!FLAC__metadata_simple_iterator_next(iterator))
1107 return die_("iterator ended early\n");
1108 our_current_position++;
1110 printf("SVA[P]\tinsert PADDING after\n");
1111 padding->length = 5;
1112 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1113 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1114 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1117 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1120 printf("SVAP[P]\tprev\n");
1121 if(!FLAC__metadata_simple_iterator_prev(iterator))
1122 return die_("iterator ended early\n");
1123 our_current_position--;
1125 printf("SVA[P]P\tprev\n");
1126 if(!FLAC__metadata_simple_iterator_prev(iterator))
1127 return die_("iterator ended early\n");
1128 our_current_position--;
1130 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1131 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1132 return die_("setting APPLICATION data");
1133 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1134 return die_("copying object");
1135 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1136 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1138 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1141 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1142 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1143 return die_("setting APPLICATION data");
1144 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1145 return die_("copying object");
1146 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1147 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1149 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1152 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1153 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1154 return die_("setting APPLICATION data");
1155 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1156 return die_("copying object");
1157 our_metadata_.blocks[our_current_position+1]->length = 0;
1158 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1159 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1161 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1164 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1165 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1166 return die_("setting APPLICATION data");
1167 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1168 return die_("copying object");
1169 delete_from_our_metadata_(our_current_position+1);
1170 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1171 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1173 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1176 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1177 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1178 return die_("setting APPLICATION data");
1179 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1180 return die_("copying object");
1181 delete_from_our_metadata_(our_current_position+1);
1182 our_metadata_.blocks[our_current_position]->is_last = true;
1183 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1184 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1186 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1189 printf("SV[A]\tset PADDING (equal size)\n");
1190 padding->length = app->length;
1191 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1192 return die_("copying object");
1193 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1194 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1196 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1199 printf("SV[P]\tinsert PADDING after\n");
1200 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1201 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1202 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1205 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1208 printf("SVP[P]\tinsert PADDING after\n");
1209 padding->length = 5;
1210 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1211 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1212 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1215 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1218 printf("SVPP[P]\tprev\n");
1219 if(!FLAC__metadata_simple_iterator_prev(iterator))
1220 return die_("iterator ended early\n");
1221 our_current_position--;
1223 printf("SVP[P]P\tprev\n");
1224 if(!FLAC__metadata_simple_iterator_prev(iterator))
1225 return die_("iterator ended early\n");
1226 our_current_position--;
1228 printf("SV[P]PP\tprev\n");
1229 if(!FLAC__metadata_simple_iterator_prev(iterator))
1230 return die_("iterator ended early\n");
1231 our_current_position--;
1233 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1234 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1235 return die_("setting APPLICATION data");
1236 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1237 return die_("copying object");
1238 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1239 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1241 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1244 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1245 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1246 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1247 delete_from_our_metadata_(our_current_position--);
1249 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1252 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1253 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1254 return die_("setting APPLICATION data");
1255 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1256 return die_("copying object");
1257 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1258 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1260 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1263 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1264 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1265 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1266 delete_from_our_metadata_(our_current_position--);
1268 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1271 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1272 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1273 return die_("setting APPLICATION data");
1274 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1275 return die_("copying object");
1276 delete_from_our_metadata_(our_current_position+1);
1277 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1278 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1280 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1283 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1284 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1285 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1286 delete_from_our_metadata_(our_current_position--);
1288 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1291 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1292 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1293 return die_("setting APPLICATION data");
1294 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1295 return die_("copying object");
1296 our_metadata_.blocks[our_current_position+1]->length = 0;
1297 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1298 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1300 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1303 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1304 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1305 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1306 delete_from_our_metadata_(our_current_position--);
1308 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1311 printf("S[V]PP\tnext\n");
1312 if(!FLAC__metadata_simple_iterator_next(iterator))
1313 return die_("iterator ended early\n");
1314 our_current_position++;
1316 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1317 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1318 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1319 delete_from_our_metadata_(our_current_position--);
1321 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1324 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1325 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1326 return die_("setting APPLICATION data");
1327 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1328 return die_("copying object");
1329 delete_from_our_metadata_(our_current_position+1);
1330 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1331 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1333 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1336 printf("delete simple iterator\n");
1338 FLAC__metadata_simple_iterator_delete(iterator);
1340 FLAC__metadata_object_delete(app);
1341 FLAC__metadata_object_delete(padding);
1343 if(!remove_file_(flacfile_))
1349 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1351 FLAC__Metadata_Iterator *iterator;
1352 FLAC__Metadata_Chain *chain;
1353 FLAC__StreamMetadata *block, *app, *padding;
1354 FLAC__byte data[2000];
1355 unsigned our_current_position;
1357 /* initialize 'data' to avoid Valgrind errors */
1358 memset(data, 0, sizeof(data));
1360 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1362 printf("generate read-only file\n");
1364 if(!generate_file_(/*include_cuesheet=*/false))
1367 if(!change_stats_(flacfile_, /*read_only=*/true))
1370 printf("create chain\n");
1372 if(0 == (chain = FLAC__metadata_chain_new()))
1373 return die_("allocating chain");
1375 printf("read chain\n");
1377 if(!read_chain_(chain, flacfile_, filename_based))
1378 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1380 printf("[S]VP\ttest initial metadata\n");
1382 if(!compare_chain_(chain, 0, 0))
1384 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1387 printf("switch file to read-write\n");
1389 if(!change_stats_(flacfile_, /*read-only=*/false))
1392 printf("create iterator\n");
1393 if(0 == (iterator = FLAC__metadata_iterator_new()))
1394 return die_("allocating memory for iterator");
1396 our_current_position = 0;
1398 FLAC__metadata_iterator_init(iterator, chain);
1400 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1401 return die_("getting block from iterator");
1403 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1405 printf("[S]VP\tmodify STREAMINFO, write\n");
1407 block->data.stream_info.sample_rate = 32000;
1408 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1409 return die_("copying object");
1411 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1412 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1413 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1415 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1418 printf("[S]VP\tnext\n");
1419 if(!FLAC__metadata_iterator_next(iterator))
1420 return die_("iterator ended early\n");
1421 our_current_position++;
1423 printf("S[V]P\tnext\n");
1424 if(!FLAC__metadata_iterator_next(iterator))
1425 return die_("iterator ended early\n");
1426 our_current_position++;
1428 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1429 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1430 return die_("getting block from iterator");
1431 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1432 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1433 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1434 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1435 return die_("setting APPLICATION data");
1436 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1437 return die_("copying object");
1438 if(!FLAC__metadata_iterator_set_block(iterator, app))
1439 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1441 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1442 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1443 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1445 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1448 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1449 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1450 return die_("copying object");
1451 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1452 return die_("setting APPLICATION data");
1453 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1454 return die_("copying object");
1455 if(!FLAC__metadata_iterator_set_block(iterator, app))
1456 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1458 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1459 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1460 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1462 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1465 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1466 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1467 return die_("copying object");
1468 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1469 return die_("setting APPLICATION data");
1470 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1471 return die_("copying object");
1472 if(!FLAC__metadata_iterator_set_block(iterator, app))
1473 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1475 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1476 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1477 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1479 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1482 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1483 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1484 return die_("copying object");
1485 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1486 return die_("setting APPLICATION data");
1487 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1488 return die_("copying object");
1489 if(!FLAC__metadata_iterator_set_block(iterator, app))
1490 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1492 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1493 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1494 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1496 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1499 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1500 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1501 return die_("copying object");
1502 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1503 return die_("setting APPLICATION data");
1504 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1505 return die_("copying object");
1506 if(!FLAC__metadata_iterator_set_block(iterator, app))
1507 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1509 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1510 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1511 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1513 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1516 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1517 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1518 return die_("creating PADDING block");
1519 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1520 return die_("copying object");
1521 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1522 return die_("setting APPLICATION data");
1523 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1524 return die_("copying object");
1525 padding->length = 0;
1526 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1527 return die_("internal error");
1528 if(!FLAC__metadata_iterator_set_block(iterator, app))
1529 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1531 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1532 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1533 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1535 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1538 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1539 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1540 return die_("copying object");
1541 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1542 return die_("setting APPLICATION data");
1543 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1544 return die_("copying object");
1545 our_metadata_.blocks[our_current_position+1]->length = 13;
1546 if(!FLAC__metadata_iterator_set_block(iterator, app))
1547 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1549 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1550 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1551 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1553 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1556 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1557 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1558 return die_("copying object");
1559 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1560 return die_("setting APPLICATION data");
1561 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1562 return die_("copying object");
1563 if(!FLAC__metadata_iterator_set_block(iterator, app))
1564 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1566 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1567 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1568 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1570 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1573 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1574 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1575 return die_("copying object");
1576 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1577 return die_("setting APPLICATION data");
1578 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1579 return die_("copying object");
1580 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1581 if(!FLAC__metadata_iterator_set_block(iterator, app))
1582 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1584 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1585 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1586 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1588 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1591 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1592 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1593 return die_("copying object");
1594 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1595 return die_("setting APPLICATION data");
1596 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1597 return die_("copying object");
1598 delete_from_our_metadata_(our_current_position+1);
1599 if(!FLAC__metadata_iterator_set_block(iterator, app))
1600 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1602 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1603 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1604 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1606 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1609 printf("SV[A]\tprev\n");
1610 if(!FLAC__metadata_iterator_prev(iterator))
1611 return die_("iterator ended early\n");
1612 our_current_position--;
1614 printf("S[V]A\tprev\n");
1615 if(!FLAC__metadata_iterator_prev(iterator))
1616 return die_("iterator ended early\n");
1617 our_current_position--;
1619 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1620 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1621 return die_("creating PADDING block");
1622 padding->length = 30;
1623 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1624 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1626 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1628 printf("[S]VP\tnext\n");
1629 if(!FLAC__metadata_iterator_next(iterator))
1630 return die_("iterator ended early\n");
1631 our_current_position++;
1633 printf("S[V]A\tinsert PADDING after\n");
1634 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1635 return die_("copying metadata");
1636 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1637 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1639 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1642 printf("SV[P]A\tinsert PADDING before\n");
1643 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1644 return die_("creating PADDING block");
1645 padding->length = 17;
1646 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1647 return die_("copying metadata");
1648 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1649 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1651 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1654 printf("SV[P]PA\tinsert PADDING before\n");
1655 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1656 return die_("creating PADDING block");
1657 padding->length = 0;
1658 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1659 return die_("copying metadata");
1660 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1661 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1663 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1666 printf("SV[P]PPA\tnext\n");
1667 if(!FLAC__metadata_iterator_next(iterator))
1668 return die_("iterator ended early\n");
1669 our_current_position++;
1671 printf("SVP[P]PA\tnext\n");
1672 if(!FLAC__metadata_iterator_next(iterator))
1673 return die_("iterator ended early\n");
1674 our_current_position++;
1676 printf("SVPP[P]A\tnext\n");
1677 if(!FLAC__metadata_iterator_next(iterator))
1678 return die_("iterator ended early\n");
1679 our_current_position++;
1681 printf("SVPPP[A]\tinsert PADDING after\n");
1682 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1683 return die_("creating PADDING block");
1684 padding->length = 57;
1685 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1686 return die_("copying metadata");
1687 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1688 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1690 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1693 printf("SVPPPA[P]\tinsert PADDING before\n");
1694 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1695 return die_("creating PADDING block");
1696 padding->length = 99;
1697 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1698 return die_("copying metadata");
1699 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1700 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1702 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1705 printf("delete iterator\n");
1706 FLAC__metadata_iterator_delete(iterator);
1707 our_current_position = 0;
1709 printf("SVPPPAPP\tmerge padding\n");
1710 FLAC__metadata_chain_merge_padding(chain);
1711 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1712 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1713 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1714 delete_from_our_metadata_(7);
1715 delete_from_our_metadata_(4);
1716 delete_from_our_metadata_(3);
1718 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1719 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1720 if(!compare_chain_(chain, 0, 0))
1722 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1725 printf("SVPAP\tsort padding\n");
1726 FLAC__metadata_chain_sort_padding(chain);
1727 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1728 delete_from_our_metadata_(2);
1730 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1731 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1732 if(!compare_chain_(chain, 0, 0))
1734 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1737 printf("create iterator\n");
1738 if(0 == (iterator = FLAC__metadata_iterator_new()))
1739 return die_("allocating memory for iterator");
1741 our_current_position = 0;
1743 FLAC__metadata_iterator_init(iterator, chain);
1745 printf("[S]VAP\tnext\n");
1746 if(!FLAC__metadata_iterator_next(iterator))
1747 return die_("iterator ended early\n");
1748 our_current_position++;
1750 printf("S[V]AP\tnext\n");
1751 if(!FLAC__metadata_iterator_next(iterator))
1752 return die_("iterator ended early\n");
1753 our_current_position++;
1755 printf("SV[A]P\tdelete middle block, replace with padding\n");
1756 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1757 return die_("creating PADDING block");
1758 padding->length = 71;
1759 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1760 return die_("copying object");
1761 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1762 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1764 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1767 printf("S[V]PP\tnext\n");
1768 if(!FLAC__metadata_iterator_next(iterator))
1769 return die_("iterator ended early\n");
1770 our_current_position++;
1772 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1773 delete_from_our_metadata_(our_current_position--);
1774 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1775 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1777 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1780 printf("S[V]P\tnext\n");
1781 if(!FLAC__metadata_iterator_next(iterator))
1782 return die_("iterator ended early\n");
1783 our_current_position++;
1785 printf("SV[P]\tdelete last block, replace with padding\n");
1786 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1787 return die_("creating PADDING block");
1788 padding->length = 219;
1789 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1790 return die_("copying object");
1791 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1792 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1794 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1797 printf("S[V]P\tnext\n");
1798 if(!FLAC__metadata_iterator_next(iterator))
1799 return die_("iterator ended early\n");
1800 our_current_position++;
1802 printf("SV[P]\tdelete last block, don't replace with padding\n");
1803 delete_from_our_metadata_(our_current_position--);
1804 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1805 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1807 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1810 printf("S[V]\tprev\n");
1811 if(!FLAC__metadata_iterator_prev(iterator))
1812 return die_("iterator ended early\n");
1813 our_current_position--;
1815 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1816 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1817 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1819 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1822 printf("delete iterator\n");
1823 FLAC__metadata_iterator_delete(iterator);
1824 our_current_position = 0;
1826 printf("SV\tmerge padding\n");
1827 FLAC__metadata_chain_merge_padding(chain);
1829 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1830 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1831 if(!compare_chain_(chain, 0, 0))
1833 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1836 printf("SV\tsort padding\n");
1837 FLAC__metadata_chain_sort_padding(chain);
1839 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1840 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1841 if(!compare_chain_(chain, 0, 0))
1843 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1846 printf("delete chain\n");
1848 FLAC__metadata_chain_delete(chain);
1850 if(!remove_file_(flacfile_))
1856 static FLAC__bool test_level_2_misc_()
1858 FLAC__Metadata_Iterator *iterator;
1859 FLAC__Metadata_Chain *chain;
1860 FLAC__IOCallbacks callbacks;
1862 memset(&callbacks, 0, sizeof(callbacks));
1863 callbacks.read = (FLAC__IOCallback_Read)fread;
1864 #ifdef FLAC__VALGRIND_TESTING
1865 callbacks.write = chain_write_cb_;
1867 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1869 callbacks.seek = chain_seek_cb_;
1870 callbacks.tell = chain_tell_cb_;
1871 callbacks.eof = chain_eof_cb_;
1873 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1875 printf("generate file\n");
1877 if(!generate_file_(/*include_cuesheet=*/false))
1880 printf("create chain\n");
1882 if(0 == (chain = FLAC__metadata_chain_new()))
1883 return die_("allocating chain");
1885 printf("read chain (filename-based)\n");
1887 if(!FLAC__metadata_chain_read(chain, flacfile_))
1888 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1890 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1892 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1893 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1894 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1895 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1896 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1899 printf("read chain (filename-based)\n");
1901 if(!FLAC__metadata_chain_read(chain, flacfile_))
1902 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1904 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1906 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1907 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1908 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1909 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1910 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1913 printf("read chain (callback-based)\n");
1915 FILE *file = fopen(flacfile_, "rb");
1917 return die_("opening file");
1918 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1920 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1925 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1927 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1928 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1929 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1930 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1931 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1934 printf("read chain (callback-based)\n");
1936 FILE *file = fopen(flacfile_, "rb");
1938 return die_("opening file");
1939 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1941 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1946 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1948 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1949 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
1951 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
1953 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1955 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1956 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1957 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
1958 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
1959 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
1962 printf("read chain (callback-based)\n");
1964 FILE *file = fopen(flacfile_, "rb");
1966 return die_("opening file");
1967 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1969 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1974 printf("create iterator\n");
1975 if(0 == (iterator = FLAC__metadata_iterator_new()))
1976 return die_("allocating memory for iterator");
1978 FLAC__metadata_iterator_init(iterator, chain);
1980 printf("[S]VP\tnext\n");
1981 if(!FLAC__metadata_iterator_next(iterator))
1982 return die_("iterator ended early\n");
1984 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
1985 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1986 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
1988 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
1990 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
1991 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
1993 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
1995 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1997 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1998 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1999 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2000 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2001 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2004 printf("delete iterator\n");
2006 FLAC__metadata_iterator_delete(iterator);
2008 printf("delete chain\n");
2010 FLAC__metadata_chain_delete(chain);
2012 if(!remove_file_(flacfile_))
2018 FLAC__bool test_metadata_file_manipulation()
2020 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2022 our_metadata_.num_blocks = 0;
2024 if(!test_level_0_())
2027 if(!test_level_1_())
2030 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2032 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2034 if(!test_level_2_misc_())