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 static char *strdup_or_die_(const char *s)
107 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
113 /* functions for working with our metadata copy */
115 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
118 FLAC__StreamMetadata *obj = block;
119 FLAC__ASSERT(position < our_metadata_.num_blocks);
121 if(0 == (obj = FLAC__metadata_object_clone(block)))
122 return die_("during FLAC__metadata_object_clone()");
124 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
125 our_metadata_.blocks[position] = obj;
127 /* set the is_last flags */
128 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
129 our_metadata_.blocks[i]->is_last = false;
130 our_metadata_.blocks[i]->is_last = true;
135 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
138 FLAC__StreamMetadata *obj = block;
140 if(0 == (obj = FLAC__metadata_object_clone(block)))
141 return die_("during FLAC__metadata_object_clone()");
143 if(position > our_metadata_.num_blocks) {
144 position = our_metadata_.num_blocks;
147 for(i = our_metadata_.num_blocks; i > position; i--)
148 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
150 our_metadata_.blocks[position] = obj;
151 our_metadata_.num_blocks++;
153 /* set the is_last flags */
154 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
155 our_metadata_.blocks[i]->is_last = false;
156 our_metadata_.blocks[i]->is_last = true;
161 static void delete_from_our_metadata_(unsigned position)
164 FLAC__ASSERT(position < our_metadata_.num_blocks);
165 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
166 for(i = position; i < our_metadata_.num_blocks - 1; i++)
167 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
168 our_metadata_.num_blocks--;
170 /* set the is_last flags */
171 if(our_metadata_.num_blocks > 0) {
172 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
173 our_metadata_.blocks[i]->is_last = false;
174 our_metadata_.blocks[i]->is_last = true;
179 * This wad of functions supports filename- and callback-based chain reading/writing.
180 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
182 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
184 static const char *tempfile_suffix = ".metadata_edit";
186 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
188 strcpy(*tempfilename, filename);
189 strcat(*tempfilename, tempfile_suffix);
191 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
197 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
200 (void)fclose(*tempfile);
204 if(0 != *tempfilename) {
205 (void)unlink(*tempfilename);
211 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
213 FLAC__ASSERT(0 != filename);
214 FLAC__ASSERT(0 != tempfile);
215 FLAC__ASSERT(0 != tempfilename);
216 FLAC__ASSERT(0 != *tempfilename);
219 (void)fclose(*tempfile);
223 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
224 /* on some flavors of windows, rename() will fail if the destination already exists */
225 if(unlink(filename) < 0) {
226 cleanup_tempfile_(tempfile, tempfilename);
231 if(0 != rename(*tempfilename, filename)) {
232 cleanup_tempfile_(tempfile, tempfilename);
236 cleanup_tempfile_(tempfile, tempfilename);
241 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
243 FLAC__ASSERT(0 != filename);
244 FLAC__ASSERT(0 != stats);
245 return (0 == stat(filename, stats));
248 void set_file_stats_(const char *filename, struct stat *stats)
250 struct utimbuf srctime;
252 FLAC__ASSERT(0 != filename);
253 FLAC__ASSERT(0 != stats);
255 srctime.actime = stats->st_atime;
256 srctime.modtime = stats->st_mtime;
257 (void)chmod(filename, stats->st_mode);
258 (void)utime(filename, &srctime);
259 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
260 (void)chown(filename, stats->st_uid, -1);
261 (void)chown(filename, -1, stats->st_gid);
265 #ifdef FLAC__VALGRIND_TESTING
266 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
268 FILE *stream = (FILE*)handle;
269 size_t ret = fwrite(ptr, size, nmemb, stream);
276 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
278 off_t o = (off_t)offset;
279 FLAC__ASSERT(offset == o);
280 return fseeko((FILE*)handle, o, whence);
283 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
285 return ftello((FILE*)handle);
288 static int chain_eof_cb_(FLAC__IOHandle handle)
290 return feof((FILE*)handle);
293 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)
296 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
298 FLAC__IOCallbacks callbacks;
300 memset(&callbacks, 0, sizeof(callbacks));
301 callbacks.read = (FLAC__IOCallback_Read)fread;
302 #ifdef FLAC__VALGRIND_TESTING
303 callbacks.write = chain_write_cb_;
305 callbacks.write = (FLAC__IOCallback_Write)fwrite;
307 callbacks.seek = chain_seek_cb_;
308 callbacks.eof = chain_eof_cb_;
310 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
312 FILE *file, *tempfile;
314 if(preserve_file_stats) {
315 if(!get_file_stats_(filename, &stats))
318 if(0 == (file = fopen(filename, "rb")))
319 return false; /*@@@ chain status still says OK though */
320 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
322 cleanup_tempfile_(&tempfile, &tempfilename);
323 return false; /*@@@ chain status still says OK though */
325 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
333 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
335 if(preserve_file_stats)
336 set_file_stats_(filename, &stats);
339 FILE *file = fopen(filename, "r+b");
341 return false; /*@@@ chain status still says OK though */
342 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
351 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
354 return FLAC__metadata_chain_read(chain, flacfile_);
356 FLAC__IOCallbacks callbacks;
358 memset(&callbacks, 0, sizeof(callbacks));
359 callbacks.read = (FLAC__IOCallback_Read)fread;
360 callbacks.seek = chain_seek_cb_;
361 callbacks.tell = chain_tell_cb_;
365 FILE *file = fopen(filename, "rb");
367 return false; /*@@@ chain status still says OK though */
368 ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
375 /* function for comparing our metadata to a FLAC__Metadata_Chain */
377 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
380 FLAC__Metadata_Iterator *iterator;
381 FLAC__StreamMetadata *block;
382 FLAC__bool next_ok = true;
384 FLAC__ASSERT(0 != chain);
386 printf("\tcomparing chain... ");
389 if(0 == (iterator = FLAC__metadata_iterator_new()))
390 return die_("allocating memory for iterator");
392 FLAC__metadata_iterator_init(iterator, chain);
399 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
400 FLAC__metadata_iterator_delete(iterator);
401 return die_("getting block from iterator");
404 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
405 FLAC__metadata_iterator_delete(iterator);
406 return die_("metadata block mismatch");
410 next_ok = FLAC__metadata_iterator_next(iterator);
411 } while(i < our_metadata_.num_blocks && next_ok);
413 FLAC__metadata_iterator_delete(iterator);
416 return die_("chain has more blocks than expected");
418 if(i < our_metadata_.num_blocks)
419 return die_("short block count in chain");
421 if(0 != current_block) {
422 printf("CURRENT_POSITION... ");
425 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
426 return die_("metadata block mismatch");
434 /* decoder callbacks for checking the file */
436 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
438 (void)decoder, (void)buffer, (void)client_data;
441 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
442 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
444 printf("content... ");
448 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
451 /* this version pays no attention to the metadata */
452 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
454 (void)decoder, (void)metadata, (void)client_data;
456 printf("%d... ", mc_our_block_number_);
459 mc_our_block_number_++;
462 /* this version is used when we want to compare to our metadata copy */
463 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
465 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
469 /* don't bother checking if we've already hit an error */
470 if(dcd->error_occurred)
473 printf("%d... ", mc_our_block_number_);
476 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
477 (void)die_("got more metadata blocks than expected");
478 dcd->error_occurred = true;
481 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
482 (void)die_("metadata block mismatch");
483 dcd->error_occurred = true;
486 mc_our_block_number_++;
489 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
491 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
494 dcd->error_occurred = true;
495 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
498 static FLAC__bool generate_file_(FLAC__bool include_extras)
500 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
501 FLAC__StreamMetadata *metadata[4];
502 unsigned i = 0, n = 0;
504 printf("generating FLAC file for test\n");
506 while(our_metadata_.num_blocks > 0)
507 delete_from_our_metadata_(0);
509 streaminfo.is_last = false;
510 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
511 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
512 streaminfo.data.stream_info.min_blocksize = 576;
513 streaminfo.data.stream_info.max_blocksize = 576;
514 streaminfo.data.stream_info.min_framesize = 0;
515 streaminfo.data.stream_info.max_framesize = 0;
516 streaminfo.data.stream_info.sample_rate = 44100;
517 streaminfo.data.stream_info.channels = 1;
518 streaminfo.data.stream_info.bits_per_sample = 8;
519 streaminfo.data.stream_info.total_samples = 0;
520 memset(streaminfo.data.stream_info.md5sum, 0, 16);
523 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
524 vorbiscomment.is_last = false;
525 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
526 vorbiscomment.length = (4 + vendor_string_length) + 4;
527 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
528 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
529 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
530 vorbiscomment.data.vorbis_comment.num_comments = 0;
531 vorbiscomment.data.vorbis_comment.comments = 0;
535 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
536 return die_("priming our metadata");
537 cuesheet->is_last = false;
538 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
539 cuesheet->data.cue_sheet.lead_in = 123;
540 cuesheet->data.cue_sheet.is_cd = false;
541 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
542 return die_("priming our metadata");
543 cuesheet->data.cue_sheet.tracks[0].number = 1;
544 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
545 return die_("priming our metadata");
549 picture.is_last = false;
550 picture.type = FLAC__METADATA_TYPE_PICTURE;
553 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
554 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
555 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
556 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
557 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
558 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
559 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
560 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
563 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
564 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
565 picture.length += strlen(picture.data.picture.mime_type);
566 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
567 picture.length += strlen((const char *)picture.data.picture.description);
568 picture.data.picture.width = 300;
569 picture.data.picture.height = 300;
570 picture.data.picture.depth = 24;
571 picture.data.picture.colors = 0;
572 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
573 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
574 picture.length += picture.data.picture.data_length;
577 padding.is_last = true;
578 padding.type = FLAC__METADATA_TYPE_PADDING;
579 padding.length = 1234;
581 metadata[n++] = &vorbiscomment;
583 metadata[n++] = cuesheet;
584 metadata[n++] = &picture;
586 metadata[n++] = &padding;
589 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
590 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
591 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
592 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
593 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
595 return die_("priming our metadata");
597 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
598 return die_("creating the encoded file");
600 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
605 static FLAC__bool test_file_(const char *filename, FLAC__StreamDecoderMetadataCallback metadata_callback)
607 FLAC__StreamDecoder *decoder;
608 decoder_client_struct decoder_client_data;
610 FLAC__ASSERT(0 != filename);
611 FLAC__ASSERT(0 != metadata_callback);
613 mc_our_block_number_ = 0;
614 decoder_client_data.error_occurred = false;
616 printf("\ttesting '%s'... ", filename);
619 if(0 == (decoder = FLAC__stream_decoder_new()))
620 return die_("couldn't allocate decoder instance");
622 FLAC__stream_decoder_set_md5_checking(decoder, true);
623 FLAC__stream_decoder_set_metadata_respond_all(decoder);
624 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) {
625 FLAC__stream_decoder_finish(decoder);
626 FLAC__stream_decoder_delete(decoder);
627 return die_("initializing decoder\n");
629 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
630 FLAC__stream_decoder_finish(decoder);
631 FLAC__stream_decoder_delete(decoder);
632 return die_("decoding file\n");
635 FLAC__stream_decoder_finish(decoder);
636 FLAC__stream_decoder_delete(decoder);
638 if(decoder_client_data.error_occurred)
641 if(mc_our_block_number_ != our_metadata_.num_blocks)
642 return die_("short metadata block count");
648 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
650 if(!grabbag__file_change_stats(filename, read_only))
651 return die_("during grabbag__file_change_stats()");
656 static FLAC__bool remove_file_(const char *filename)
658 while(our_metadata_.num_blocks > 0)
659 delete_from_our_metadata_(0);
661 if(!grabbag__file_remove_file(filename))
662 return die_("removing file");
667 static FLAC__bool test_level_0_()
669 FLAC__StreamMetadata streaminfo;
670 FLAC__StreamMetadata *tags = 0;
671 FLAC__StreamMetadata *cuesheet = 0;
672 FLAC__StreamMetadata *picture = 0;
674 printf("\n\n++++++ testing level 0 interface\n");
676 if(!generate_file_(/*include_extras=*/true))
679 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
682 printf("testing FLAC__metadata_get_streaminfo()... ");
684 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
685 return die_("during FLAC__metadata_get_streaminfo()");
687 /* check to see if some basic data matches (c.f. generate_file_()) */
688 if(streaminfo.data.stream_info.channels != 1)
689 return die_("mismatch in streaminfo.data.stream_info.channels");
690 if(streaminfo.data.stream_info.bits_per_sample != 8)
691 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
692 if(streaminfo.data.stream_info.sample_rate != 44100)
693 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
694 if(streaminfo.data.stream_info.min_blocksize != 576)
695 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
696 if(streaminfo.data.stream_info.max_blocksize != 576)
697 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
701 printf("testing FLAC__metadata_get_tags()... ");
703 if(!FLAC__metadata_get_tags(flacfile_, &tags))
704 return die_("during FLAC__metadata_get_tags()");
706 /* check to see if some basic data matches (c.f. generate_file_()) */
707 if(tags->data.vorbis_comment.num_comments != 0)
708 return die_("mismatch in tags->data.vorbis_comment.num_comments");
712 FLAC__metadata_object_delete(tags);
714 printf("testing FLAC__metadata_get_cuesheet()... ");
716 if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
717 return die_("during FLAC__metadata_get_cuesheet()");
719 /* check to see if some basic data matches (c.f. generate_file_()) */
720 if(cuesheet->data.cue_sheet.lead_in != 123)
721 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
725 FLAC__metadata_object_delete(cuesheet);
727 printf("testing FLAC__metadata_get_picture()... ");
729 if(!FLAC__metadata_get_picture(flacfile_, &picture, /*type=*/(FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1), /*max_colors=*/(unsigned)(-1)))
730 return die_("during FLAC__metadata_get_picture()");
732 /* check to see if some basic data matches (c.f. generate_file_()) */
733 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
734 return die_("mismatch in picture->data.picture.type");
738 FLAC__metadata_object_delete(picture);
740 if(!remove_file_(flacfile_))
746 static FLAC__bool test_level_1_()
748 FLAC__Metadata_SimpleIterator *iterator;
749 FLAC__StreamMetadata *block, *app, *padding;
750 FLAC__byte data[1000];
751 unsigned our_current_position = 0;
753 /* initialize 'data' to avoid Valgrind errors */
754 memset(data, 0, sizeof(data));
756 printf("\n\n++++++ testing level 1 interface\n");
758 /************************************************************/
760 printf("simple iterator on read-only file\n");
762 if(!generate_file_(/*include_extras=*/false))
765 if(!change_stats_(flacfile_, /*read_only=*/true))
768 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
771 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
772 return die_("FLAC__metadata_simple_iterator_new()");
774 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
775 return die_("FLAC__metadata_simple_iterator_init() returned false");
777 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
778 if(FLAC__metadata_simple_iterator_is_writable(iterator))
779 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
781 printf("iterate forwards\n");
783 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
784 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
785 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
786 return die_("getting block 0");
787 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
788 return die_("expected STREAMINFO type");
790 return die_("expected is_last to be false");
791 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
792 return die_("bad STREAMINFO length");
793 /* check to see if some basic data matches (c.f. generate_file_()) */
794 if(block->data.stream_info.channels != 1)
795 return die_("mismatch in channels");
796 if(block->data.stream_info.bits_per_sample != 8)
797 return die_("mismatch in bits_per_sample");
798 if(block->data.stream_info.sample_rate != 44100)
799 return die_("mismatch in sample_rate");
800 if(block->data.stream_info.min_blocksize != 576)
801 return die_("mismatch in min_blocksize");
802 if(block->data.stream_info.max_blocksize != 576)
803 return die_("mismatch in max_blocksize");
804 FLAC__metadata_object_delete(block);
806 if(!FLAC__metadata_simple_iterator_next(iterator))
807 return die_("forward iterator ended early");
808 our_current_position++;
810 if(!FLAC__metadata_simple_iterator_next(iterator))
811 return die_("forward iterator ended early");
812 our_current_position++;
814 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
815 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
816 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
817 return die_("getting block 2");
818 if(block->type != FLAC__METADATA_TYPE_PADDING)
819 return die_("expected PADDING type");
821 return die_("expected is_last to be true");
822 /* check to see if some basic data matches (c.f. generate_file_()) */
823 if(block->length != 1234)
824 return die_("bad PADDING length");
825 FLAC__metadata_object_delete(block);
827 if(FLAC__metadata_simple_iterator_next(iterator))
828 return die_("forward iterator returned true but should have returned false");
830 printf("iterate backwards\n");
831 if(!FLAC__metadata_simple_iterator_prev(iterator))
832 return die_("reverse iterator ended early");
833 if(!FLAC__metadata_simple_iterator_prev(iterator))
834 return die_("reverse iterator ended early");
835 if(FLAC__metadata_simple_iterator_prev(iterator))
836 return die_("reverse iterator returned true but should have returned false");
838 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
840 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
841 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
843 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
845 FLAC__metadata_simple_iterator_delete(iterator);
847 /************************************************************/
849 printf("simple iterator on writable file\n");
851 if(!change_stats_(flacfile_, /*read-only=*/false))
854 printf("creating APPLICATION block\n");
856 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
857 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
858 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
860 printf("creating PADDING block\n");
862 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
863 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
864 padding->length = 20;
866 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
867 return die_("FLAC__metadata_simple_iterator_new()");
869 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
870 return die_("FLAC__metadata_simple_iterator_init() returned false");
871 our_current_position = 0;
873 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
875 printf("[S]VP\ttry to write over STREAMINFO block...\n");
876 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
877 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
879 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
881 printf("[S]VP\tnext\n");
882 if(!FLAC__metadata_simple_iterator_next(iterator))
883 return die_("iterator ended early\n");
884 our_current_position++;
886 printf("S[V]P\tnext\n");
887 if(!FLAC__metadata_simple_iterator_next(iterator))
888 return die_("iterator ended early\n");
889 our_current_position++;
891 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
892 padding->length = 25;
893 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
894 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
895 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
898 printf("SVP[P]\tprev\n");
899 if(!FLAC__metadata_simple_iterator_prev(iterator))
900 return die_("iterator ended early\n");
901 our_current_position--;
903 printf("SV[P]P\tprev\n");
904 if(!FLAC__metadata_simple_iterator_prev(iterator))
905 return die_("iterator ended early\n");
906 our_current_position--;
908 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
909 padding->length = 30;
910 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
911 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
912 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
915 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
918 printf("SV[P]PP\tprev\n");
919 if(!FLAC__metadata_simple_iterator_prev(iterator))
920 return die_("iterator ended early\n");
921 our_current_position--;
923 printf("S[V]PPP\tprev\n");
924 if(!FLAC__metadata_simple_iterator_prev(iterator))
925 return die_("iterator ended early\n");
926 our_current_position--;
928 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
929 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
930 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
932 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
935 printf("[S]VPPP\tnext\n");
936 if(!FLAC__metadata_simple_iterator_next(iterator))
937 return die_("iterator ended early\n");
938 our_current_position++;
940 printf("S[V]PPP\tnext\n");
941 if(!FLAC__metadata_simple_iterator_next(iterator))
942 return die_("iterator ended early\n");
943 our_current_position++;
945 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
946 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
947 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
948 our_current_position--;
950 printf("S[V]PPP\tnext\n");
951 if(!FLAC__metadata_simple_iterator_next(iterator))
952 return die_("iterator ended early\n");
953 our_current_position++;
955 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
956 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
957 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
958 delete_from_our_metadata_(our_current_position--);
960 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
963 printf("S[V]PP\tnext\n");
964 if(!FLAC__metadata_simple_iterator_next(iterator))
965 return die_("iterator ended early\n");
966 our_current_position++;
968 printf("SV[P]P\tnext\n");
969 if(!FLAC__metadata_simple_iterator_next(iterator))
970 return die_("iterator ended early\n");
971 our_current_position++;
973 printf("SVP[P]\tdelete (last block), replace with padding\n");
974 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
975 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
976 our_current_position--;
978 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
981 printf("SV[P]P\tnext\n");
982 if(!FLAC__metadata_simple_iterator_next(iterator))
983 return die_("iterator ended early\n");
984 our_current_position++;
986 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
987 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
988 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
989 delete_from_our_metadata_(our_current_position--);
991 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
994 printf("SV[P]\tprev\n");
995 if(!FLAC__metadata_simple_iterator_prev(iterator))
996 return die_("iterator ended early\n");
997 our_current_position--;
999 printf("S[V]P\tprev\n");
1000 if(!FLAC__metadata_simple_iterator_prev(iterator))
1001 return die_("iterator ended early\n");
1002 our_current_position--;
1004 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1005 FLAC__ASSERT(our_current_position == 0);
1006 block = FLAC__metadata_simple_iterator_get_block(iterator);
1007 block->data.stream_info.sample_rate = 32000;
1008 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1009 return die_("copying object");
1010 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1011 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1012 FLAC__metadata_object_delete(block);
1014 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1017 printf("[S]VP\tnext\n");
1018 if(!FLAC__metadata_simple_iterator_next(iterator))
1019 return die_("iterator ended early\n");
1020 our_current_position++;
1022 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1023 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1024 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1025 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1026 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1028 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1030 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1033 printf("SV[A]P\tnext\n");
1034 if(!FLAC__metadata_simple_iterator_next(iterator))
1035 return die_("iterator ended early\n");
1036 our_current_position++;
1038 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1039 app->data.application.id[0] = 'f'; /* twiddle the id */
1040 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1041 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1042 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1044 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1046 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1049 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1050 app->data.application.id[0] = 'g'; /* twiddle the id */
1051 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1052 return die_("setting APPLICATION data");
1053 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1054 return die_("copying object");
1055 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1056 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1058 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1061 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1062 app->data.application.id[0] = 'h'; /* twiddle the id */
1063 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1064 return die_("setting APPLICATION data");
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("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1074 app->data.application.id[0] = 'i'; /* twiddle the id */
1075 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1076 return die_("setting APPLICATION data");
1077 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1078 return die_("copying object");
1079 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1080 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1081 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1083 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1086 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1087 app->data.application.id[0] = 'j'; /* twiddle the id */
1088 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1089 return die_("setting APPLICATION data");
1090 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1091 return die_("copying object");
1092 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1093 return die_("copying object");
1094 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1095 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1096 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1098 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1101 printf("SVA[A]PP\tnext\n");
1102 if(!FLAC__metadata_simple_iterator_next(iterator))
1103 return die_("iterator ended early\n");
1104 our_current_position++;
1106 printf("SVAA[P]P\tnext\n");
1107 if(!FLAC__metadata_simple_iterator_next(iterator))
1108 return die_("iterator ended early\n");
1109 our_current_position++;
1111 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1112 padding->length = 5;
1113 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1114 return die_("copying object");
1115 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1116 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1118 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1121 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1122 app->data.application.id[0] = 'k'; /* twiddle the id */
1123 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1124 return die_("copying object");
1125 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1126 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1128 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1131 printf("SVAAP[A]\tset PADDING (equal)\n");
1132 padding->length = 27;
1133 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1134 return die_("copying object");
1135 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1136 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1138 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1141 printf("SVAAP[P]\tprev\n");
1142 if(!FLAC__metadata_simple_iterator_prev(iterator))
1143 return die_("iterator ended early\n");
1144 our_current_position--;
1146 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1147 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1148 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1149 delete_from_our_metadata_(our_current_position--);
1151 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1154 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1155 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1156 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1157 delete_from_our_metadata_(our_current_position--);
1159 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1162 printf("SV[A]P\tnext\n");
1163 if(!FLAC__metadata_simple_iterator_next(iterator))
1164 return die_("iterator ended early\n");
1165 our_current_position++;
1167 printf("SVA[P]\tinsert PADDING after\n");
1168 padding->length = 5;
1169 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1170 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1171 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1174 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1177 printf("SVAP[P]\tprev\n");
1178 if(!FLAC__metadata_simple_iterator_prev(iterator))
1179 return die_("iterator ended early\n");
1180 our_current_position--;
1182 printf("SVA[P]P\tprev\n");
1183 if(!FLAC__metadata_simple_iterator_prev(iterator))
1184 return die_("iterator ended early\n");
1185 our_current_position--;
1187 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1188 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1189 return die_("setting APPLICATION data");
1190 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1191 return die_("copying object");
1192 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1193 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1195 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1198 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1199 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1200 return die_("setting APPLICATION data");
1201 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1202 return die_("copying object");
1203 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1204 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1206 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1209 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1210 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1211 return die_("setting APPLICATION data");
1212 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1213 return die_("copying object");
1214 our_metadata_.blocks[our_current_position+1]->length = 0;
1215 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1216 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1218 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1221 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1222 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1223 return die_("setting APPLICATION data");
1224 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1225 return die_("copying object");
1226 delete_from_our_metadata_(our_current_position+1);
1227 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1228 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1230 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1233 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1234 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1235 return die_("setting APPLICATION data");
1236 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1237 return die_("copying object");
1238 delete_from_our_metadata_(our_current_position+1);
1239 our_metadata_.blocks[our_current_position]->is_last = true;
1240 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1241 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1243 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1246 printf("SV[A]\tset PADDING (equal size)\n");
1247 padding->length = app->length;
1248 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1249 return die_("copying object");
1250 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1251 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1253 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1256 printf("SV[P]\tinsert PADDING after\n");
1257 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1258 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1259 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1262 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1265 printf("SVP[P]\tinsert PADDING after\n");
1266 padding->length = 5;
1267 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1268 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1269 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1272 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1275 printf("SVPP[P]\tprev\n");
1276 if(!FLAC__metadata_simple_iterator_prev(iterator))
1277 return die_("iterator ended early\n");
1278 our_current_position--;
1280 printf("SVP[P]P\tprev\n");
1281 if(!FLAC__metadata_simple_iterator_prev(iterator))
1282 return die_("iterator ended early\n");
1283 our_current_position--;
1285 printf("SV[P]PP\tprev\n");
1286 if(!FLAC__metadata_simple_iterator_prev(iterator))
1287 return die_("iterator ended early\n");
1288 our_current_position--;
1290 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1291 if(!FLAC__metadata_object_application_set_data(app, data, 101, 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 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1296 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1298 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1301 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1302 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1303 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1304 delete_from_our_metadata_(our_current_position--);
1306 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1309 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1310 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1311 return die_("setting APPLICATION data");
1312 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1313 return die_("copying object");
1314 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1315 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1317 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1320 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1321 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1322 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1323 delete_from_our_metadata_(our_current_position--);
1325 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1328 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1329 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1330 return die_("setting APPLICATION data");
1331 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1332 return die_("copying object");
1333 delete_from_our_metadata_(our_current_position+1);
1334 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1335 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1337 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1340 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1341 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1342 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1343 delete_from_our_metadata_(our_current_position--);
1345 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1348 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1349 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1350 return die_("setting APPLICATION data");
1351 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1352 return die_("copying object");
1353 our_metadata_.blocks[our_current_position+1]->length = 0;
1354 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1355 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1357 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1360 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1361 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1362 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1363 delete_from_our_metadata_(our_current_position--);
1365 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1368 printf("S[V]PP\tnext\n");
1369 if(!FLAC__metadata_simple_iterator_next(iterator))
1370 return die_("iterator ended early\n");
1371 our_current_position++;
1373 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1374 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1375 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1376 delete_from_our_metadata_(our_current_position--);
1378 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1381 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1382 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1383 return die_("setting APPLICATION data");
1384 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1385 return die_("copying object");
1386 delete_from_our_metadata_(our_current_position+1);
1387 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1388 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1390 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1393 printf("delete simple iterator\n");
1395 FLAC__metadata_simple_iterator_delete(iterator);
1397 FLAC__metadata_object_delete(app);
1398 FLAC__metadata_object_delete(padding);
1400 if(!remove_file_(flacfile_))
1406 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1408 FLAC__Metadata_Iterator *iterator;
1409 FLAC__Metadata_Chain *chain;
1410 FLAC__StreamMetadata *block, *app, *padding;
1411 FLAC__byte data[2000];
1412 unsigned our_current_position;
1414 /* initialize 'data' to avoid Valgrind errors */
1415 memset(data, 0, sizeof(data));
1417 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1419 printf("generate read-only file\n");
1421 if(!generate_file_(/*include_extras=*/false))
1424 if(!change_stats_(flacfile_, /*read_only=*/true))
1427 printf("create chain\n");
1429 if(0 == (chain = FLAC__metadata_chain_new()))
1430 return die_("allocating chain");
1432 printf("read chain\n");
1434 if(!read_chain_(chain, flacfile_, filename_based))
1435 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1437 printf("[S]VP\ttest initial metadata\n");
1439 if(!compare_chain_(chain, 0, 0))
1441 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1444 printf("switch file to read-write\n");
1446 if(!change_stats_(flacfile_, /*read-only=*/false))
1449 printf("create iterator\n");
1450 if(0 == (iterator = FLAC__metadata_iterator_new()))
1451 return die_("allocating memory for iterator");
1453 our_current_position = 0;
1455 FLAC__metadata_iterator_init(iterator, chain);
1457 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1458 return die_("getting block from iterator");
1460 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1462 printf("[S]VP\tmodify STREAMINFO, write\n");
1464 block->data.stream_info.sample_rate = 32000;
1465 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1466 return die_("copying object");
1468 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1469 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1470 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1472 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1475 printf("[S]VP\tnext\n");
1476 if(!FLAC__metadata_iterator_next(iterator))
1477 return die_("iterator ended early\n");
1478 our_current_position++;
1480 printf("S[V]P\tnext\n");
1481 if(!FLAC__metadata_iterator_next(iterator))
1482 return die_("iterator ended early\n");
1483 our_current_position++;
1485 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1486 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1487 return die_("getting block from iterator");
1488 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1489 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1490 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1491 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1492 return die_("setting APPLICATION data");
1493 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1494 return die_("copying object");
1495 if(!FLAC__metadata_iterator_set_block(iterator, app))
1496 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1498 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1499 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1500 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1502 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1505 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1506 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1507 return die_("copying object");
1508 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1509 return die_("setting APPLICATION data");
1510 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1511 return die_("copying object");
1512 if(!FLAC__metadata_iterator_set_block(iterator, app))
1513 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1515 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1516 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1517 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1519 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1522 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1523 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1524 return die_("copying object");
1525 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1526 return die_("setting APPLICATION data");
1527 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1528 return die_("copying object");
1529 if(!FLAC__metadata_iterator_set_block(iterator, app))
1530 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1532 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1533 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1534 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1536 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1539 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1540 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1541 return die_("copying object");
1542 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1543 return die_("setting APPLICATION data");
1544 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1545 return die_("copying object");
1546 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=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1550 return die_c_("during FLAC__metadata_chain_write(chain, false, 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]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\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, 33, 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]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1574 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1575 return die_("creating PADDING block");
1576 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1577 return die_("copying object");
1578 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1579 return die_("setting APPLICATION data");
1580 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1581 return die_("copying object");
1582 padding->length = 0;
1583 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1584 return die_("internal error");
1585 if(!FLAC__metadata_iterator_set_block(iterator, app))
1586 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1588 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1589 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1590 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1592 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1595 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1596 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1597 return die_("copying object");
1598 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1599 return die_("setting APPLICATION data");
1600 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1601 return die_("copying object");
1602 our_metadata_.blocks[our_current_position+1]->length = 13;
1603 if(!FLAC__metadata_iterator_set_block(iterator, app))
1604 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1606 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1607 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1608 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1610 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1613 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1614 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1615 return die_("copying object");
1616 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1617 return die_("setting APPLICATION data");
1618 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1619 return die_("copying object");
1620 if(!FLAC__metadata_iterator_set_block(iterator, app))
1621 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1623 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1624 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1625 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1627 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1630 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1631 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1632 return die_("copying object");
1633 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1634 return die_("setting APPLICATION data");
1635 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1636 return die_("copying object");
1637 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1638 if(!FLAC__metadata_iterator_set_block(iterator, app))
1639 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1641 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1642 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1643 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1645 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1648 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1649 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1650 return die_("copying object");
1651 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1652 return die_("setting APPLICATION data");
1653 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1654 return die_("copying object");
1655 delete_from_our_metadata_(our_current_position+1);
1656 if(!FLAC__metadata_iterator_set_block(iterator, app))
1657 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1659 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1660 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1661 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1663 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1666 printf("SV[A]\tprev\n");
1667 if(!FLAC__metadata_iterator_prev(iterator))
1668 return die_("iterator ended early\n");
1669 our_current_position--;
1671 printf("S[V]A\tprev\n");
1672 if(!FLAC__metadata_iterator_prev(iterator))
1673 return die_("iterator ended early\n");
1674 our_current_position--;
1676 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1677 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1678 return die_("creating PADDING block");
1679 padding->length = 30;
1680 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1681 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1683 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1685 printf("[S]VP\tnext\n");
1686 if(!FLAC__metadata_iterator_next(iterator))
1687 return die_("iterator ended early\n");
1688 our_current_position++;
1690 printf("S[V]A\tinsert PADDING after\n");
1691 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1692 return die_("copying metadata");
1693 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1694 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1696 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1699 printf("SV[P]A\tinsert PADDING before\n");
1700 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1701 return die_("creating PADDING block");
1702 padding->length = 17;
1703 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1704 return die_("copying metadata");
1705 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1706 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1708 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1711 printf("SV[P]PA\tinsert PADDING before\n");
1712 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1713 return die_("creating PADDING block");
1714 padding->length = 0;
1715 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1716 return die_("copying metadata");
1717 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1718 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1720 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1723 printf("SV[P]PPA\tnext\n");
1724 if(!FLAC__metadata_iterator_next(iterator))
1725 return die_("iterator ended early\n");
1726 our_current_position++;
1728 printf("SVP[P]PA\tnext\n");
1729 if(!FLAC__metadata_iterator_next(iterator))
1730 return die_("iterator ended early\n");
1731 our_current_position++;
1733 printf("SVPP[P]A\tnext\n");
1734 if(!FLAC__metadata_iterator_next(iterator))
1735 return die_("iterator ended early\n");
1736 our_current_position++;
1738 printf("SVPPP[A]\tinsert PADDING after\n");
1739 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1740 return die_("creating PADDING block");
1741 padding->length = 57;
1742 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1743 return die_("copying metadata");
1744 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1745 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1747 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1750 printf("SVPPPA[P]\tinsert PADDING before\n");
1751 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1752 return die_("creating PADDING block");
1753 padding->length = 99;
1754 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1755 return die_("copying metadata");
1756 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1757 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1759 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1762 printf("delete iterator\n");
1763 FLAC__metadata_iterator_delete(iterator);
1764 our_current_position = 0;
1766 printf("SVPPPAPP\tmerge padding\n");
1767 FLAC__metadata_chain_merge_padding(chain);
1768 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1769 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1770 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1771 delete_from_our_metadata_(7);
1772 delete_from_our_metadata_(4);
1773 delete_from_our_metadata_(3);
1775 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1776 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1777 if(!compare_chain_(chain, 0, 0))
1779 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1782 printf("SVPAP\tsort padding\n");
1783 FLAC__metadata_chain_sort_padding(chain);
1784 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1785 delete_from_our_metadata_(2);
1787 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1788 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1789 if(!compare_chain_(chain, 0, 0))
1791 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1794 printf("create iterator\n");
1795 if(0 == (iterator = FLAC__metadata_iterator_new()))
1796 return die_("allocating memory for iterator");
1798 our_current_position = 0;
1800 FLAC__metadata_iterator_init(iterator, chain);
1802 printf("[S]VAP\tnext\n");
1803 if(!FLAC__metadata_iterator_next(iterator))
1804 return die_("iterator ended early\n");
1805 our_current_position++;
1807 printf("S[V]AP\tnext\n");
1808 if(!FLAC__metadata_iterator_next(iterator))
1809 return die_("iterator ended early\n");
1810 our_current_position++;
1812 printf("SV[A]P\tdelete middle block, replace with padding\n");
1813 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1814 return die_("creating PADDING block");
1815 padding->length = 71;
1816 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1817 return die_("copying object");
1818 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1819 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1821 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1824 printf("S[V]PP\tnext\n");
1825 if(!FLAC__metadata_iterator_next(iterator))
1826 return die_("iterator ended early\n");
1827 our_current_position++;
1829 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1830 delete_from_our_metadata_(our_current_position--);
1831 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1832 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1834 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1837 printf("S[V]P\tnext\n");
1838 if(!FLAC__metadata_iterator_next(iterator))
1839 return die_("iterator ended early\n");
1840 our_current_position++;
1842 printf("SV[P]\tdelete last block, replace with padding\n");
1843 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1844 return die_("creating PADDING block");
1845 padding->length = 219;
1846 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1847 return die_("copying object");
1848 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1849 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1851 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1854 printf("S[V]P\tnext\n");
1855 if(!FLAC__metadata_iterator_next(iterator))
1856 return die_("iterator ended early\n");
1857 our_current_position++;
1859 printf("SV[P]\tdelete last block, don't replace with padding\n");
1860 delete_from_our_metadata_(our_current_position--);
1861 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1862 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1864 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1867 printf("S[V]\tprev\n");
1868 if(!FLAC__metadata_iterator_prev(iterator))
1869 return die_("iterator ended early\n");
1870 our_current_position--;
1872 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1873 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1874 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1876 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1879 printf("delete iterator\n");
1880 FLAC__metadata_iterator_delete(iterator);
1881 our_current_position = 0;
1883 printf("SV\tmerge padding\n");
1884 FLAC__metadata_chain_merge_padding(chain);
1886 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1887 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1888 if(!compare_chain_(chain, 0, 0))
1890 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1893 printf("SV\tsort padding\n");
1894 FLAC__metadata_chain_sort_padding(chain);
1896 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1897 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1898 if(!compare_chain_(chain, 0, 0))
1900 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1903 printf("delete chain\n");
1905 FLAC__metadata_chain_delete(chain);
1907 if(!remove_file_(flacfile_))
1913 static FLAC__bool test_level_2_misc_()
1915 FLAC__Metadata_Iterator *iterator;
1916 FLAC__Metadata_Chain *chain;
1917 FLAC__IOCallbacks callbacks;
1919 memset(&callbacks, 0, sizeof(callbacks));
1920 callbacks.read = (FLAC__IOCallback_Read)fread;
1921 #ifdef FLAC__VALGRIND_TESTING
1922 callbacks.write = chain_write_cb_;
1924 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1926 callbacks.seek = chain_seek_cb_;
1927 callbacks.tell = chain_tell_cb_;
1928 callbacks.eof = chain_eof_cb_;
1930 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1932 printf("generate file\n");
1934 if(!generate_file_(/*include_extras=*/false))
1937 printf("create chain\n");
1939 if(0 == (chain = FLAC__metadata_chain_new()))
1940 return die_("allocating chain");
1942 printf("read chain (filename-based)\n");
1944 if(!FLAC__metadata_chain_read(chain, flacfile_))
1945 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1947 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1949 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1950 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1951 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1952 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1953 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1956 printf("read chain (filename-based)\n");
1958 if(!FLAC__metadata_chain_read(chain, flacfile_))
1959 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1961 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1963 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1964 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1965 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1966 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1967 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1970 printf("read chain (callback-based)\n");
1972 FILE *file = fopen(flacfile_, "rb");
1974 return die_("opening file");
1975 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1977 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1982 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1984 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1985 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1986 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1987 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1988 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1991 printf("read chain (callback-based)\n");
1993 FILE *file = fopen(flacfile_, "rb");
1995 return die_("opening file");
1996 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1998 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2003 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2005 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2006 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2008 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2010 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2012 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2013 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2014 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2015 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2016 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2019 printf("read chain (callback-based)\n");
2021 FILE *file = fopen(flacfile_, "rb");
2023 return die_("opening file");
2024 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2026 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2031 printf("create iterator\n");
2032 if(0 == (iterator = FLAC__metadata_iterator_new()))
2033 return die_("allocating memory for iterator");
2035 FLAC__metadata_iterator_init(iterator, chain);
2037 printf("[S]VP\tnext\n");
2038 if(!FLAC__metadata_iterator_next(iterator))
2039 return die_("iterator ended early\n");
2041 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2042 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2043 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2045 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2047 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2048 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2050 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2052 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2054 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2055 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2056 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2057 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2058 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2061 printf("delete iterator\n");
2063 FLAC__metadata_iterator_delete(iterator);
2065 printf("delete chain\n");
2067 FLAC__metadata_chain_delete(chain);
2069 if(!remove_file_(flacfile_))
2075 FLAC__bool test_metadata_file_manipulation()
2077 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2079 our_metadata_.num_blocks = 0;
2081 if(!test_level_0_())
2084 if(!test_level_1_())
2087 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2089 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2091 if(!test_level_2_misc_())