1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002,2003,2004,2005,2006,2007 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 #include <string.h> /* for memcpy()/memset() */
26 #if defined _MSC_VER || defined __MINGW32__
27 #include <sys/utime.h> /* for utime() */
28 #include <io.h> /* for chmod() */
29 #if _MSC_VER <= 1600 /* @@@ [2G limit] */
34 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
35 #include <utime.h> /* for utime() */
36 #include <unistd.h> /* for chown(), unlink() */
38 #include <sys/stat.h> /* for stat(), maybe chmod() */
39 #include "FLAC/assert.h"
40 #include "FLAC/stream_decoder.h"
41 #include "FLAC/metadata.h"
42 #include "share/grabbag.h"
43 #include "test_libs_common/file_utils_flac.h"
44 #include "test_libs_common/metadata_utils.h"
48 /******************************************************************************
49 The general strategy of these tests (for interface levels 1 and 2) is
50 to create a dummy FLAC file with a known set of initial metadata
51 blocks, then keep a mirror locally of what we expect the metadata to be
52 after each operation. Then testing becomes a simple matter of running
53 a FLAC__StreamDecoder over the dummy file after each operation, comparing
54 the decoded metadata to what's in our local copy. If there are any
55 differences in the metadata, or the actual audio data is corrupted, we
56 will catch it while decoding.
57 ******************************************************************************/
60 FLAC__bool error_occurred;
61 } decoder_client_struct;
64 FLAC__StreamMetadata *blocks[64];
66 } our_metadata_struct;
68 /* our copy of the metadata in flacfilename() */
69 static our_metadata_struct our_metadata_;
71 /* the current block number that corresponds to the position of the iterator we are testing */
72 static unsigned mc_our_block_number_ = 0;
74 static const char *flacfilename(FLAC__bool is_ogg)
76 return is_ogg? "metadata.oga" : "metadata.flac";
79 static FLAC__bool die_(const char *msg)
81 printf("ERROR: %s\n", msg);
85 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
87 printf("ERROR: %s\n", msg);
88 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
92 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
94 printf("ERROR: %s\n", msg);
95 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
99 static void *malloc_or_die_(size_t size)
101 void *x = malloc(size);
103 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
109 static char *strdup_or_die_(const char *s)
113 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
119 /* functions for working with our metadata copy */
121 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
124 FLAC__StreamMetadata *obj = block;
125 FLAC__ASSERT(position < our_metadata_.num_blocks);
127 if(0 == (obj = FLAC__metadata_object_clone(block)))
128 return die_("during FLAC__metadata_object_clone()");
130 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
131 our_metadata_.blocks[position] = obj;
133 /* set the is_last flags */
134 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
135 our_metadata_.blocks[i]->is_last = false;
136 our_metadata_.blocks[i]->is_last = true;
141 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
144 FLAC__StreamMetadata *obj = block;
146 if(0 == (obj = FLAC__metadata_object_clone(block)))
147 return die_("during FLAC__metadata_object_clone()");
149 if(position > our_metadata_.num_blocks) {
150 position = our_metadata_.num_blocks;
153 for(i = our_metadata_.num_blocks; i > position; i--)
154 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
156 our_metadata_.blocks[position] = obj;
157 our_metadata_.num_blocks++;
159 /* set the is_last flags */
160 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
161 our_metadata_.blocks[i]->is_last = false;
162 our_metadata_.blocks[i]->is_last = true;
167 static void delete_from_our_metadata_(unsigned position)
170 FLAC__ASSERT(position < our_metadata_.num_blocks);
171 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
172 for(i = position; i < our_metadata_.num_blocks - 1; i++)
173 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
174 our_metadata_.num_blocks--;
176 /* set the is_last flags */
177 if(our_metadata_.num_blocks > 0) {
178 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
179 our_metadata_.blocks[i]->is_last = false;
180 our_metadata_.blocks[i]->is_last = true;
185 * This wad of functions supports filename- and callback-based chain reading/writing.
186 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
188 static FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
190 static const char *tempfile_suffix = ".metadata_edit";
192 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
194 strcpy(*tempfilename, filename);
195 strcat(*tempfilename, tempfile_suffix);
197 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
203 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
206 (void)fclose(*tempfile);
210 if(0 != *tempfilename) {
211 (void)unlink(*tempfilename);
217 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
219 FLAC__ASSERT(0 != filename);
220 FLAC__ASSERT(0 != tempfile);
221 FLAC__ASSERT(0 != tempfilename);
222 FLAC__ASSERT(0 != *tempfilename);
225 (void)fclose(*tempfile);
229 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
230 /* on some flavors of windows, rename() will fail if the destination already exists */
231 if(unlink(filename) < 0) {
232 cleanup_tempfile_(tempfile, tempfilename);
237 if(0 != rename(*tempfilename, filename)) {
238 cleanup_tempfile_(tempfile, tempfilename);
242 cleanup_tempfile_(tempfile, tempfilename);
247 static FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
249 FLAC__ASSERT(0 != filename);
250 FLAC__ASSERT(0 != stats);
251 return (0 == stat(filename, stats));
254 static void set_file_stats_(const char *filename, struct stat *stats)
256 struct utimbuf srctime;
258 FLAC__ASSERT(0 != filename);
259 FLAC__ASSERT(0 != stats);
261 srctime.actime = stats->st_atime;
262 srctime.modtime = stats->st_mtime;
263 (void)chmod(filename, stats->st_mode);
264 (void)utime(filename, &srctime);
265 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
266 (void)chown(filename, stats->st_uid, -1);
267 (void)chown(filename, -1, stats->st_gid);
271 #ifdef FLAC__VALGRIND_TESTING
272 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
274 FILE *stream = (FILE*)handle;
275 size_t ret = fwrite(ptr, size, nmemb, stream);
282 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
284 off_t o = (off_t)offset;
285 FLAC__ASSERT(offset == o);
286 return fseeko((FILE*)handle, o, whence);
289 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
291 return ftello((FILE*)handle);
294 static int chain_eof_cb_(FLAC__IOHandle handle)
296 return feof((FILE*)handle);
299 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)
302 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
304 FLAC__IOCallbacks callbacks;
306 memset(&callbacks, 0, sizeof(callbacks));
307 callbacks.read = (FLAC__IOCallback_Read)fread;
308 #ifdef FLAC__VALGRIND_TESTING
309 callbacks.write = chain_write_cb_;
311 callbacks.write = (FLAC__IOCallback_Write)fwrite;
313 callbacks.seek = chain_seek_cb_;
314 callbacks.eof = chain_eof_cb_;
316 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
318 FILE *file, *tempfile = 0;
320 if(preserve_file_stats) {
321 if(!get_file_stats_(filename, &stats))
324 if(0 == (file = fopen(filename, "rb")))
325 return false; /*@@@@ chain status still says OK though */
326 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
328 cleanup_tempfile_(&tempfile, &tempfilename);
329 return false; /*@@@@ chain status still says OK though */
331 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
339 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
341 if(preserve_file_stats)
342 set_file_stats_(filename, &stats);
345 FILE *file = fopen(filename, "r+b");
347 return false; /*@@@@ chain status still says OK though */
348 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
357 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based, FLAC__bool is_ogg)
361 FLAC__metadata_chain_read_ogg(chain, flacfilename(is_ogg)) :
362 FLAC__metadata_chain_read(chain, flacfilename(is_ogg))
365 FLAC__IOCallbacks callbacks;
367 memset(&callbacks, 0, sizeof(callbacks));
368 callbacks.read = (FLAC__IOCallback_Read)fread;
369 callbacks.seek = chain_seek_cb_;
370 callbacks.tell = chain_tell_cb_;
374 FILE *file = fopen(filename, "rb");
376 return false; /*@@@@ chain status still says OK though */
378 FLAC__metadata_chain_read_ogg_with_callbacks(chain, (FLAC__IOHandle)file, callbacks) :
379 FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)
387 /* function for comparing our metadata to a FLAC__Metadata_Chain */
389 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
392 FLAC__Metadata_Iterator *iterator;
393 FLAC__StreamMetadata *block;
394 FLAC__bool next_ok = true;
396 FLAC__ASSERT(0 != chain);
398 printf("\tcomparing chain... ");
401 if(0 == (iterator = FLAC__metadata_iterator_new()))
402 return die_("allocating memory for iterator");
404 FLAC__metadata_iterator_init(iterator, chain);
411 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
412 FLAC__metadata_iterator_delete(iterator);
413 return die_("getting block from iterator");
416 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
417 FLAC__metadata_iterator_delete(iterator);
418 return die_("metadata block mismatch");
422 next_ok = FLAC__metadata_iterator_next(iterator);
423 } while(i < our_metadata_.num_blocks && next_ok);
425 FLAC__metadata_iterator_delete(iterator);
428 return die_("chain has more blocks than expected");
430 if(i < our_metadata_.num_blocks)
431 return die_("short block count in chain");
433 if(0 != current_block) {
434 printf("CURRENT_POSITION... ");
437 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
438 return die_("metadata block mismatch");
446 /* decoder callbacks for checking the file */
448 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
450 (void)decoder, (void)buffer, (void)client_data;
453 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
454 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
456 printf("content... ");
460 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
463 /* this version pays no attention to the metadata */
464 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
466 (void)decoder, (void)metadata, (void)client_data;
468 printf("%d... ", mc_our_block_number_);
471 mc_our_block_number_++;
474 /* this version is used when we want to compare to our metadata copy */
475 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
477 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
481 /* don't bother checking if we've already hit an error */
482 if(dcd->error_occurred)
485 printf("%d... ", mc_our_block_number_);
488 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
489 (void)die_("got more metadata blocks than expected");
490 dcd->error_occurred = true;
493 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
494 (void)die_("metadata block mismatch");
495 dcd->error_occurred = true;
498 mc_our_block_number_++;
501 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
503 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
506 dcd->error_occurred = true;
507 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
510 static FLAC__bool generate_file_(FLAC__bool include_extras, FLAC__bool is_ogg)
512 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
513 FLAC__StreamMetadata *metadata[4];
514 unsigned i = 0, n = 0;
516 printf("generating %sFLAC file for test\n", is_ogg? "Ogg " : "");
518 while(our_metadata_.num_blocks > 0)
519 delete_from_our_metadata_(0);
521 streaminfo.is_last = false;
522 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
523 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
524 streaminfo.data.stream_info.min_blocksize = 576;
525 streaminfo.data.stream_info.max_blocksize = 576;
526 streaminfo.data.stream_info.min_framesize = 0;
527 streaminfo.data.stream_info.max_framesize = 0;
528 streaminfo.data.stream_info.sample_rate = 44100;
529 streaminfo.data.stream_info.channels = 1;
530 streaminfo.data.stream_info.bits_per_sample = 8;
531 streaminfo.data.stream_info.total_samples = 0;
532 memset(streaminfo.data.stream_info.md5sum, 0, 16);
535 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
536 vorbiscomment.is_last = false;
537 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
538 vorbiscomment.length = (4 + vendor_string_length) + 4;
539 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
540 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
541 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
542 vorbiscomment.data.vorbis_comment.num_comments = 0;
543 vorbiscomment.data.vorbis_comment.comments = 0;
547 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
548 return die_("priming our metadata");
549 cuesheet->is_last = false;
550 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
551 cuesheet->data.cue_sheet.lead_in = 123;
552 cuesheet->data.cue_sheet.is_cd = false;
553 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
554 return die_("priming our metadata");
555 cuesheet->data.cue_sheet.tracks[0].number = 1;
556 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
557 return die_("priming our metadata");
561 picture.is_last = false;
562 picture.type = FLAC__METADATA_TYPE_PICTURE;
565 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
566 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
567 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
568 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
569 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
570 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
571 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
572 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
575 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
576 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
577 picture.length += strlen(picture.data.picture.mime_type);
578 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
579 picture.length += strlen((const char *)picture.data.picture.description);
580 picture.data.picture.width = 300;
581 picture.data.picture.height = 300;
582 picture.data.picture.depth = 24;
583 picture.data.picture.colors = 0;
584 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
585 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
586 picture.length += picture.data.picture.data_length;
589 padding.is_last = true;
590 padding.type = FLAC__METADATA_TYPE_PADDING;
591 padding.length = 1234;
593 metadata[n++] = &vorbiscomment;
595 metadata[n++] = cuesheet;
596 metadata[n++] = &picture;
598 metadata[n++] = &padding;
601 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
602 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
603 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
604 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
605 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
607 return die_("priming our metadata");
609 if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), 0, 512 * 1024, &streaminfo, metadata, n))
610 return die_("creating the encoded file");
612 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
613 free(picture.data.picture.mime_type);
614 free(picture.data.picture.description);
615 free(picture.data.picture.data);
617 FLAC__metadata_object_delete(cuesheet);
622 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
624 const char *filename = flacfilename(is_ogg);
625 FLAC__StreamDecoder *decoder;
626 decoder_client_struct decoder_client_data;
628 FLAC__ASSERT(0 != metadata_callback);
630 mc_our_block_number_ = 0;
631 decoder_client_data.error_occurred = false;
633 printf("\ttesting '%s'... ", filename);
636 if(0 == (decoder = FLAC__stream_decoder_new()))
637 return die_("couldn't allocate decoder instance");
639 FLAC__stream_decoder_set_md5_checking(decoder, true);
640 FLAC__stream_decoder_set_metadata_respond_all(decoder);
643 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
644 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
645 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
647 (void)FLAC__stream_decoder_finish(decoder);
648 FLAC__stream_decoder_delete(decoder);
649 return die_("initializing decoder\n");
651 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
652 (void)FLAC__stream_decoder_finish(decoder);
653 FLAC__stream_decoder_delete(decoder);
654 return die_("decoding file\n");
657 (void)FLAC__stream_decoder_finish(decoder);
658 FLAC__stream_decoder_delete(decoder);
660 if(decoder_client_data.error_occurred)
663 if(mc_our_block_number_ != our_metadata_.num_blocks)
664 return die_("short metadata block count");
670 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
672 if(!grabbag__file_change_stats(filename, read_only))
673 return die_("during grabbag__file_change_stats()");
678 static FLAC__bool remove_file_(const char *filename)
680 while(our_metadata_.num_blocks > 0)
681 delete_from_our_metadata_(0);
683 if(!grabbag__file_remove_file(filename))
684 return die_("removing file");
689 static FLAC__bool test_level_0_(void)
691 FLAC__StreamMetadata streaminfo;
692 FLAC__StreamMetadata *tags = 0;
693 FLAC__StreamMetadata *cuesheet = 0;
694 FLAC__StreamMetadata *picture = 0;
696 printf("\n\n++++++ testing level 0 interface\n");
698 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
701 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
704 printf("testing FLAC__metadata_get_streaminfo()... ");
706 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
707 return die_("during FLAC__metadata_get_streaminfo()");
709 /* check to see if some basic data matches (c.f. generate_file_()) */
710 if(streaminfo.data.stream_info.channels != 1)
711 return die_("mismatch in streaminfo.data.stream_info.channels");
712 if(streaminfo.data.stream_info.bits_per_sample != 8)
713 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
714 if(streaminfo.data.stream_info.sample_rate != 44100)
715 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
716 if(streaminfo.data.stream_info.min_blocksize != 576)
717 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
718 if(streaminfo.data.stream_info.max_blocksize != 576)
719 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
723 printf("testing FLAC__metadata_get_tags()... ");
725 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
726 return die_("during FLAC__metadata_get_tags()");
728 /* check to see if some basic data matches (c.f. generate_file_()) */
729 if(tags->data.vorbis_comment.num_comments != 0)
730 return die_("mismatch in tags->data.vorbis_comment.num_comments");
734 FLAC__metadata_object_delete(tags);
736 printf("testing FLAC__metadata_get_cuesheet()... ");
738 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
739 return die_("during FLAC__metadata_get_cuesheet()");
741 /* check to see if some basic data matches (c.f. generate_file_()) */
742 if(cuesheet->data.cue_sheet.lead_in != 123)
743 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
747 FLAC__metadata_object_delete(cuesheet);
749 printf("testing FLAC__metadata_get_picture()... ");
751 if(!FLAC__metadata_get_picture(flacfilename(/*is_ogg=*/false), &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)))
752 return die_("during FLAC__metadata_get_picture()");
754 /* check to see if some basic data matches (c.f. generate_file_()) */
755 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
756 return die_("mismatch in picture->data.picture.type");
760 FLAC__metadata_object_delete(picture);
762 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
768 static FLAC__bool test_level_1_(void)
770 FLAC__Metadata_SimpleIterator *iterator;
771 FLAC__StreamMetadata *block, *app, *padding;
772 FLAC__byte data[1000];
773 unsigned our_current_position = 0;
775 /* initialize 'data' to avoid Valgrind errors */
776 memset(data, 0, sizeof(data));
778 printf("\n\n++++++ testing level 1 interface\n");
780 /************************************************************/
782 printf("simple iterator on read-only file\n");
784 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
787 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
790 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
793 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
794 return die_("FLAC__metadata_simple_iterator_new()");
796 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
797 return die_("FLAC__metadata_simple_iterator_init() returned false");
799 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
800 if(FLAC__metadata_simple_iterator_is_writable(iterator))
801 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
803 printf("iterate forwards\n");
805 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
806 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
807 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
808 return die_("getting block 0");
809 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
810 return die_("expected STREAMINFO type");
812 return die_("expected is_last to be false");
813 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
814 return die_("bad STREAMINFO length");
815 /* check to see if some basic data matches (c.f. generate_file_()) */
816 if(block->data.stream_info.channels != 1)
817 return die_("mismatch in channels");
818 if(block->data.stream_info.bits_per_sample != 8)
819 return die_("mismatch in bits_per_sample");
820 if(block->data.stream_info.sample_rate != 44100)
821 return die_("mismatch in sample_rate");
822 if(block->data.stream_info.min_blocksize != 576)
823 return die_("mismatch in min_blocksize");
824 if(block->data.stream_info.max_blocksize != 576)
825 return die_("mismatch in max_blocksize");
826 FLAC__metadata_object_delete(block);
828 if(!FLAC__metadata_simple_iterator_next(iterator))
829 return die_("forward iterator ended early");
830 our_current_position++;
832 if(!FLAC__metadata_simple_iterator_next(iterator))
833 return die_("forward iterator ended early");
834 our_current_position++;
836 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
837 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
838 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
839 return die_("getting block 2");
840 if(block->type != FLAC__METADATA_TYPE_PADDING)
841 return die_("expected PADDING type");
843 return die_("expected is_last to be true");
844 /* check to see if some basic data matches (c.f. generate_file_()) */
845 if(block->length != 1234)
846 return die_("bad PADDING length");
847 FLAC__metadata_object_delete(block);
849 if(FLAC__metadata_simple_iterator_next(iterator))
850 return die_("forward iterator returned true but should have returned false");
852 printf("iterate backwards\n");
853 if(!FLAC__metadata_simple_iterator_prev(iterator))
854 return die_("reverse iterator ended early");
855 if(!FLAC__metadata_simple_iterator_prev(iterator))
856 return die_("reverse iterator ended early");
857 if(FLAC__metadata_simple_iterator_prev(iterator))
858 return die_("reverse iterator returned true but should have returned false");
860 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
862 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
863 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
865 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
867 FLAC__metadata_simple_iterator_delete(iterator);
869 /************************************************************/
871 printf("simple iterator on writable file\n");
873 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
876 printf("creating APPLICATION block\n");
878 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
879 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
880 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
882 printf("creating PADDING block\n");
884 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
885 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
886 padding->length = 20;
888 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
889 return die_("FLAC__metadata_simple_iterator_new()");
891 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
892 return die_("FLAC__metadata_simple_iterator_init() returned false");
893 our_current_position = 0;
895 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
897 printf("[S]VP\ttry to write over STREAMINFO block...\n");
898 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
899 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
901 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
903 printf("[S]VP\tnext\n");
904 if(!FLAC__metadata_simple_iterator_next(iterator))
905 return die_("iterator ended early\n");
906 our_current_position++;
908 printf("S[V]P\tnext\n");
909 if(!FLAC__metadata_simple_iterator_next(iterator))
910 return die_("iterator ended early\n");
911 our_current_position++;
913 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
914 padding->length = 25;
915 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
916 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
917 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
920 printf("SVP[P]\tprev\n");
921 if(!FLAC__metadata_simple_iterator_prev(iterator))
922 return die_("iterator ended early\n");
923 our_current_position--;
925 printf("SV[P]P\tprev\n");
926 if(!FLAC__metadata_simple_iterator_prev(iterator))
927 return die_("iterator ended early\n");
928 our_current_position--;
930 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
931 padding->length = 30;
932 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
933 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
934 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
937 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
940 printf("SV[P]PP\tprev\n");
941 if(!FLAC__metadata_simple_iterator_prev(iterator))
942 return die_("iterator ended early\n");
943 our_current_position--;
945 printf("S[V]PPP\tprev\n");
946 if(!FLAC__metadata_simple_iterator_prev(iterator))
947 return die_("iterator ended early\n");
948 our_current_position--;
950 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
951 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
952 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
954 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
957 printf("[S]VPPP\tnext\n");
958 if(!FLAC__metadata_simple_iterator_next(iterator))
959 return die_("iterator ended early\n");
960 our_current_position++;
962 printf("S[V]PPP\tnext\n");
963 if(!FLAC__metadata_simple_iterator_next(iterator))
964 return die_("iterator ended early\n");
965 our_current_position++;
967 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
968 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
969 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
970 our_current_position--;
972 printf("S[V]PPP\tnext\n");
973 if(!FLAC__metadata_simple_iterator_next(iterator))
974 return die_("iterator ended early\n");
975 our_current_position++;
977 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
978 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
979 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
980 delete_from_our_metadata_(our_current_position--);
982 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
985 printf("S[V]PP\tnext\n");
986 if(!FLAC__metadata_simple_iterator_next(iterator))
987 return die_("iterator ended early\n");
988 our_current_position++;
990 printf("SV[P]P\tnext\n");
991 if(!FLAC__metadata_simple_iterator_next(iterator))
992 return die_("iterator ended early\n");
993 our_current_position++;
995 printf("SVP[P]\tdelete (last block), replace with padding\n");
996 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
997 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
998 our_current_position--;
1000 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1003 printf("SV[P]P\tnext\n");
1004 if(!FLAC__metadata_simple_iterator_next(iterator))
1005 return die_("iterator ended early\n");
1006 our_current_position++;
1008 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1009 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1010 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1011 delete_from_our_metadata_(our_current_position--);
1013 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1016 printf("SV[P]\tprev\n");
1017 if(!FLAC__metadata_simple_iterator_prev(iterator))
1018 return die_("iterator ended early\n");
1019 our_current_position--;
1021 printf("S[V]P\tprev\n");
1022 if(!FLAC__metadata_simple_iterator_prev(iterator))
1023 return die_("iterator ended early\n");
1024 our_current_position--;
1026 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1027 FLAC__ASSERT(our_current_position == 0);
1028 block = FLAC__metadata_simple_iterator_get_block(iterator);
1029 block->data.stream_info.sample_rate = 32000;
1030 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1031 return die_("copying object");
1032 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1033 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1034 FLAC__metadata_object_delete(block);
1036 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1039 printf("[S]VP\tnext\n");
1040 if(!FLAC__metadata_simple_iterator_next(iterator))
1041 return die_("iterator ended early\n");
1042 our_current_position++;
1044 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1045 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1046 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1047 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1048 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1050 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1052 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1055 printf("SV[A]P\tnext\n");
1056 if(!FLAC__metadata_simple_iterator_next(iterator))
1057 return die_("iterator ended early\n");
1058 our_current_position++;
1060 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1061 app->data.application.id[0] = 'f'; /* twiddle the id */
1062 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1063 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1064 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1066 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1068 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1071 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1072 app->data.application.id[0] = 'g'; /* twiddle the id */
1073 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1074 return die_("setting APPLICATION data");
1075 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1076 return die_("copying object");
1077 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1078 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1080 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1083 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1084 app->data.application.id[0] = 'h'; /* twiddle the id */
1085 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1086 return die_("setting APPLICATION data");
1087 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1088 return die_("copying object");
1089 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1090 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1092 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1095 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1096 app->data.application.id[0] = 'i'; /* twiddle the id */
1097 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1098 return die_("setting APPLICATION data");
1099 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1100 return die_("copying object");
1101 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1102 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1103 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1105 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1108 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1109 app->data.application.id[0] = 'j'; /* twiddle the id */
1110 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1111 return die_("setting APPLICATION data");
1112 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1113 return die_("copying object");
1114 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1115 return die_("copying object");
1116 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1117 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1118 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1120 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1123 printf("SVA[A]PP\tnext\n");
1124 if(!FLAC__metadata_simple_iterator_next(iterator))
1125 return die_("iterator ended early\n");
1126 our_current_position++;
1128 printf("SVAA[P]P\tnext\n");
1129 if(!FLAC__metadata_simple_iterator_next(iterator))
1130 return die_("iterator ended early\n");
1131 our_current_position++;
1133 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1134 padding->length = 5;
1135 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1136 return die_("copying object");
1137 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1138 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1140 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1143 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1144 app->data.application.id[0] = 'k'; /* twiddle the id */
1145 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1146 return die_("copying object");
1147 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1148 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1150 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1153 printf("SVAAP[A]\tset PADDING (equal)\n");
1154 padding->length = 27;
1155 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1156 return die_("copying object");
1157 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1158 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1160 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1163 printf("SVAAP[P]\tprev\n");
1164 if(!FLAC__metadata_simple_iterator_prev(iterator))
1165 return die_("iterator ended early\n");
1166 our_current_position--;
1168 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1169 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1170 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1171 delete_from_our_metadata_(our_current_position--);
1173 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1176 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1177 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1178 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1179 delete_from_our_metadata_(our_current_position--);
1181 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1184 printf("SV[A]P\tnext\n");
1185 if(!FLAC__metadata_simple_iterator_next(iterator))
1186 return die_("iterator ended early\n");
1187 our_current_position++;
1189 printf("SVA[P]\tinsert PADDING after\n");
1190 padding->length = 5;
1191 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1192 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1193 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1196 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1199 printf("SVAP[P]\tprev\n");
1200 if(!FLAC__metadata_simple_iterator_prev(iterator))
1201 return die_("iterator ended early\n");
1202 our_current_position--;
1204 printf("SVA[P]P\tprev\n");
1205 if(!FLAC__metadata_simple_iterator_prev(iterator))
1206 return die_("iterator ended early\n");
1207 our_current_position--;
1209 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1210 if(!FLAC__metadata_object_application_set_data(app, data, 32, 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 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1215 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1217 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1220 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1221 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1222 return die_("setting APPLICATION data");
1223 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1224 return die_("copying object");
1225 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1226 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1228 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1231 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1232 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1233 return die_("setting APPLICATION data");
1234 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1235 return die_("copying object");
1236 our_metadata_.blocks[our_current_position+1]->length = 0;
1237 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1238 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1240 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1243 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1244 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1245 return die_("setting APPLICATION data");
1246 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1247 return die_("copying object");
1248 delete_from_our_metadata_(our_current_position+1);
1249 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1250 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1252 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1255 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1256 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1257 return die_("setting APPLICATION data");
1258 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1259 return die_("copying object");
1260 delete_from_our_metadata_(our_current_position+1);
1261 our_metadata_.blocks[our_current_position]->is_last = true;
1262 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1263 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1265 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1268 printf("SV[A]\tset PADDING (equal size)\n");
1269 padding->length = app->length;
1270 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1271 return die_("copying object");
1272 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1273 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1275 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1278 printf("SV[P]\tinsert PADDING after\n");
1279 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1280 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1281 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1284 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1287 printf("SVP[P]\tinsert PADDING after\n");
1288 padding->length = 5;
1289 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1290 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1291 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1294 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1297 printf("SVPP[P]\tprev\n");
1298 if(!FLAC__metadata_simple_iterator_prev(iterator))
1299 return die_("iterator ended early\n");
1300 our_current_position--;
1302 printf("SVP[P]P\tprev\n");
1303 if(!FLAC__metadata_simple_iterator_prev(iterator))
1304 return die_("iterator ended early\n");
1305 our_current_position--;
1307 printf("SV[P]PP\tprev\n");
1308 if(!FLAC__metadata_simple_iterator_prev(iterator))
1309 return die_("iterator ended early\n");
1310 our_current_position--;
1312 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1313 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1314 return die_("setting APPLICATION data");
1315 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1316 return die_("copying object");
1317 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1318 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1320 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1323 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1324 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1325 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1326 delete_from_our_metadata_(our_current_position--);
1328 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1331 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1332 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1333 return die_("setting APPLICATION data");
1334 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1335 return die_("copying object");
1336 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1337 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1339 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1342 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1343 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1344 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1345 delete_from_our_metadata_(our_current_position--);
1347 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1350 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1351 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1352 return die_("setting APPLICATION data");
1353 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1354 return die_("copying object");
1355 delete_from_our_metadata_(our_current_position+1);
1356 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1357 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1359 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1362 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1363 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1364 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1365 delete_from_our_metadata_(our_current_position--);
1367 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1370 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1371 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1372 return die_("setting APPLICATION data");
1373 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1374 return die_("copying object");
1375 our_metadata_.blocks[our_current_position+1]->length = 0;
1376 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1377 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1379 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1382 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1383 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1384 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1385 delete_from_our_metadata_(our_current_position--);
1387 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1390 printf("S[V]PP\tnext\n");
1391 if(!FLAC__metadata_simple_iterator_next(iterator))
1392 return die_("iterator ended early\n");
1393 our_current_position++;
1395 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1396 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1397 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1398 delete_from_our_metadata_(our_current_position--);
1400 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1403 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1404 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1405 return die_("setting APPLICATION data");
1406 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1407 return die_("copying object");
1408 delete_from_our_metadata_(our_current_position+1);
1409 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1410 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1412 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1415 printf("delete simple iterator\n");
1417 FLAC__metadata_simple_iterator_delete(iterator);
1419 FLAC__metadata_object_delete(app);
1420 FLAC__metadata_object_delete(padding);
1422 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1428 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1430 FLAC__Metadata_Iterator *iterator;
1431 FLAC__Metadata_Chain *chain;
1432 FLAC__StreamMetadata *block, *app, *padding;
1433 FLAC__byte data[2000];
1434 unsigned our_current_position;
1436 /* initialize 'data' to avoid Valgrind errors */
1437 memset(data, 0, sizeof(data));
1439 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1441 printf("generate read-only file\n");
1443 if(!generate_file_(/*include_extras=*/false, is_ogg))
1446 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1449 printf("create chain\n");
1451 if(0 == (chain = FLAC__metadata_chain_new()))
1452 return die_("allocating chain");
1454 printf("read chain\n");
1456 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1457 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1459 printf("[S]VP\ttest initial metadata\n");
1461 if(!compare_chain_(chain, 0, 0))
1463 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1469 printf("switch file to read-write\n");
1471 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1474 printf("create iterator\n");
1475 if(0 == (iterator = FLAC__metadata_iterator_new()))
1476 return die_("allocating memory for iterator");
1478 our_current_position = 0;
1480 FLAC__metadata_iterator_init(iterator, chain);
1482 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1483 return die_("getting block from iterator");
1485 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1487 printf("[S]VP\tmodify STREAMINFO, write\n");
1489 block->data.stream_info.sample_rate = 32000;
1490 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1491 return die_("copying object");
1493 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1494 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1495 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1497 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1500 printf("[S]VP\tnext\n");
1501 if(!FLAC__metadata_iterator_next(iterator))
1502 return die_("iterator ended early\n");
1503 our_current_position++;
1505 printf("S[V]P\tnext\n");
1506 if(!FLAC__metadata_iterator_next(iterator))
1507 return die_("iterator ended early\n");
1508 our_current_position++;
1510 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1511 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1512 return die_("getting block from iterator");
1513 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1514 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1515 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1516 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1517 return die_("setting APPLICATION data");
1518 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1519 return die_("copying object");
1520 if(!FLAC__metadata_iterator_set_block(iterator, app))
1521 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1523 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1524 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1525 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1527 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1530 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1531 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1532 return die_("copying object");
1533 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1534 return die_("setting APPLICATION data");
1535 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1536 return die_("copying object");
1537 if(!FLAC__metadata_iterator_set_block(iterator, app))
1538 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1540 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1541 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1542 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1544 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1547 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1548 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1549 return die_("copying object");
1550 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1551 return die_("setting APPLICATION data");
1552 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1553 return die_("copying object");
1554 if(!FLAC__metadata_iterator_set_block(iterator, app))
1555 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1557 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1558 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1559 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1561 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1564 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1565 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1566 return die_("copying object");
1567 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1568 return die_("setting APPLICATION data");
1569 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1570 return die_("copying object");
1571 if(!FLAC__metadata_iterator_set_block(iterator, app))
1572 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1574 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1575 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1576 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1578 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1581 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1582 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1583 return die_("copying object");
1584 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1585 return die_("setting APPLICATION data");
1586 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1587 return die_("copying object");
1588 if(!FLAC__metadata_iterator_set_block(iterator, app))
1589 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1591 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1592 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1593 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1595 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1598 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1599 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1600 return die_("creating PADDING block");
1601 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1602 return die_("copying object");
1603 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1604 return die_("setting APPLICATION data");
1605 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1606 return die_("copying object");
1607 padding->length = 0;
1608 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1609 return die_("internal error");
1610 if(!FLAC__metadata_iterator_set_block(iterator, app))
1611 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1613 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1614 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1615 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1617 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1620 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1621 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1622 return die_("copying object");
1623 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1624 return die_("setting APPLICATION data");
1625 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1626 return die_("copying object");
1627 our_metadata_.blocks[our_current_position+1]->length = 13;
1628 if(!FLAC__metadata_iterator_set_block(iterator, app))
1629 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1631 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1632 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1633 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1635 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1638 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1639 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1640 return die_("copying object");
1641 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1642 return die_("setting APPLICATION data");
1643 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1644 return die_("copying object");
1645 if(!FLAC__metadata_iterator_set_block(iterator, app))
1646 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1648 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1649 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1650 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1652 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1655 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1656 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1657 return die_("copying object");
1658 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1659 return die_("setting APPLICATION data");
1660 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1661 return die_("copying object");
1662 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1663 if(!FLAC__metadata_iterator_set_block(iterator, app))
1664 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1666 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1667 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1668 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1670 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1673 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1674 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1675 return die_("copying object");
1676 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1677 return die_("setting APPLICATION data");
1678 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1679 return die_("copying object");
1680 delete_from_our_metadata_(our_current_position+1);
1681 if(!FLAC__metadata_iterator_set_block(iterator, app))
1682 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1684 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1685 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1686 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1688 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1691 printf("SV[A]\tprev\n");
1692 if(!FLAC__metadata_iterator_prev(iterator))
1693 return die_("iterator ended early\n");
1694 our_current_position--;
1696 printf("S[V]A\tprev\n");
1697 if(!FLAC__metadata_iterator_prev(iterator))
1698 return die_("iterator ended early\n");
1699 our_current_position--;
1701 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1702 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1703 return die_("creating PADDING block");
1704 padding->length = 30;
1705 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1706 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1708 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1710 printf("[S]VP\tnext\n");
1711 if(!FLAC__metadata_iterator_next(iterator))
1712 return die_("iterator ended early\n");
1713 our_current_position++;
1715 printf("S[V]A\tinsert PADDING after\n");
1716 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1717 return die_("copying metadata");
1718 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1719 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1721 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1724 printf("SV[P]A\tinsert PADDING before\n");
1725 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1726 return die_("creating PADDING block");
1727 padding->length = 17;
1728 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1729 return die_("copying metadata");
1730 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1731 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1733 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1736 printf("SV[P]PA\tinsert PADDING before\n");
1737 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1738 return die_("creating PADDING block");
1739 padding->length = 0;
1740 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1741 return die_("copying metadata");
1742 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1743 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1745 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1748 printf("SV[P]PPA\tnext\n");
1749 if(!FLAC__metadata_iterator_next(iterator))
1750 return die_("iterator ended early\n");
1751 our_current_position++;
1753 printf("SVP[P]PA\tnext\n");
1754 if(!FLAC__metadata_iterator_next(iterator))
1755 return die_("iterator ended early\n");
1756 our_current_position++;
1758 printf("SVPP[P]A\tnext\n");
1759 if(!FLAC__metadata_iterator_next(iterator))
1760 return die_("iterator ended early\n");
1761 our_current_position++;
1763 printf("SVPPP[A]\tinsert PADDING after\n");
1764 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1765 return die_("creating PADDING block");
1766 padding->length = 57;
1767 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1768 return die_("copying metadata");
1769 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1770 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1772 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1775 printf("SVPPPA[P]\tinsert PADDING before\n");
1776 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1777 return die_("creating PADDING block");
1778 padding->length = 99;
1779 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1780 return die_("copying metadata");
1781 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1782 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1784 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1787 printf("delete iterator\n");
1788 FLAC__metadata_iterator_delete(iterator);
1789 our_current_position = 0;
1791 printf("SVPPPAPP\tmerge padding\n");
1792 FLAC__metadata_chain_merge_padding(chain);
1793 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1794 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1795 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1796 delete_from_our_metadata_(7);
1797 delete_from_our_metadata_(4);
1798 delete_from_our_metadata_(3);
1800 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1801 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1802 if(!compare_chain_(chain, 0, 0))
1804 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1807 printf("SVPAP\tsort padding\n");
1808 FLAC__metadata_chain_sort_padding(chain);
1809 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1810 delete_from_our_metadata_(2);
1812 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1813 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1814 if(!compare_chain_(chain, 0, 0))
1816 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1819 printf("create iterator\n");
1820 if(0 == (iterator = FLAC__metadata_iterator_new()))
1821 return die_("allocating memory for iterator");
1823 our_current_position = 0;
1825 FLAC__metadata_iterator_init(iterator, chain);
1827 printf("[S]VAP\tnext\n");
1828 if(!FLAC__metadata_iterator_next(iterator))
1829 return die_("iterator ended early\n");
1830 our_current_position++;
1832 printf("S[V]AP\tnext\n");
1833 if(!FLAC__metadata_iterator_next(iterator))
1834 return die_("iterator ended early\n");
1835 our_current_position++;
1837 printf("SV[A]P\tdelete middle block, replace with padding\n");
1838 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1839 return die_("creating PADDING block");
1840 padding->length = 71;
1841 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1842 return die_("copying object");
1843 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1844 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1846 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1849 printf("S[V]PP\tnext\n");
1850 if(!FLAC__metadata_iterator_next(iterator))
1851 return die_("iterator ended early\n");
1852 our_current_position++;
1854 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1855 delete_from_our_metadata_(our_current_position--);
1856 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1857 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1859 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1862 printf("S[V]P\tnext\n");
1863 if(!FLAC__metadata_iterator_next(iterator))
1864 return die_("iterator ended early\n");
1865 our_current_position++;
1867 printf("SV[P]\tdelete last block, replace with padding\n");
1868 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1869 return die_("creating PADDING block");
1870 padding->length = 219;
1871 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1872 return die_("copying object");
1873 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1874 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1876 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1879 printf("S[V]P\tnext\n");
1880 if(!FLAC__metadata_iterator_next(iterator))
1881 return die_("iterator ended early\n");
1882 our_current_position++;
1884 printf("SV[P]\tdelete last block, don't replace with padding\n");
1885 delete_from_our_metadata_(our_current_position--);
1886 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1887 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1889 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1892 printf("S[V]\tprev\n");
1893 if(!FLAC__metadata_iterator_prev(iterator))
1894 return die_("iterator ended early\n");
1895 our_current_position--;
1897 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1898 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1899 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1901 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1904 printf("delete iterator\n");
1905 FLAC__metadata_iterator_delete(iterator);
1906 our_current_position = 0;
1908 printf("SV\tmerge padding\n");
1909 FLAC__metadata_chain_merge_padding(chain);
1911 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1912 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1913 if(!compare_chain_(chain, 0, 0))
1915 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1918 printf("SV\tsort padding\n");
1919 FLAC__metadata_chain_sort_padding(chain);
1921 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1922 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1923 if(!compare_chain_(chain, 0, 0))
1925 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1929 printf("delete chain\n");
1931 FLAC__metadata_chain_delete(chain);
1933 if(!remove_file_(flacfilename(is_ogg)))
1939 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1941 FLAC__Metadata_Iterator *iterator;
1942 FLAC__Metadata_Chain *chain;
1943 FLAC__IOCallbacks callbacks;
1945 memset(&callbacks, 0, sizeof(callbacks));
1946 callbacks.read = (FLAC__IOCallback_Read)fread;
1947 #ifdef FLAC__VALGRIND_TESTING
1948 callbacks.write = chain_write_cb_;
1950 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1952 callbacks.seek = chain_seek_cb_;
1953 callbacks.tell = chain_tell_cb_;
1954 callbacks.eof = chain_eof_cb_;
1956 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1958 printf("generate file\n");
1960 if(!generate_file_(/*include_extras=*/false, is_ogg))
1963 printf("create chain\n");
1965 if(0 == (chain = FLAC__metadata_chain_new()))
1966 return die_("allocating chain");
1968 printf("read chain (filename-based)\n");
1970 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1971 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1973 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1975 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1976 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1977 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1978 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1979 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1982 printf("read chain (filename-based)\n");
1984 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1985 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1987 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1989 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1990 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1991 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1992 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1993 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1996 printf("read chain (callback-based)\n");
1998 FILE *file = fopen(flacfilename(is_ogg), "rb");
2000 return die_("opening file");
2001 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2003 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2008 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2010 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2011 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2012 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2013 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2014 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2017 printf("read chain (callback-based)\n");
2019 FILE *file = fopen(flacfilename(is_ogg), "rb");
2021 return die_("opening file");
2022 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2024 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2029 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2031 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2032 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2034 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2036 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2038 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2039 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2040 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2041 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2042 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2045 printf("read chain (callback-based)\n");
2047 FILE *file = fopen(flacfilename(is_ogg), "rb");
2049 return die_("opening file");
2050 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2052 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2057 printf("create iterator\n");
2058 if(0 == (iterator = FLAC__metadata_iterator_new()))
2059 return die_("allocating memory for iterator");
2061 FLAC__metadata_iterator_init(iterator, chain);
2063 printf("[S]VP\tnext\n");
2064 if(!FLAC__metadata_iterator_next(iterator))
2065 return die_("iterator ended early\n");
2067 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2068 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2069 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2071 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2073 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2074 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2076 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2078 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2080 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2081 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2082 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2083 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2084 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2087 printf("delete iterator\n");
2089 FLAC__metadata_iterator_delete(iterator);
2091 printf("delete chain\n");
2093 FLAC__metadata_chain_delete(chain);
2095 if(!remove_file_(flacfilename(is_ogg)))
2101 FLAC__bool test_metadata_file_manipulation(void)
2103 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2105 our_metadata_.num_blocks = 0;
2107 if(!test_level_0_())
2110 if(!test_level_1_())
2113 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2115 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2117 if(!test_level_2_misc_(/*is_ogg=*/false))
2120 if(FLAC_API_SUPPORTS_OGG_FLAC) {
2121 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2123 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2126 /* when ogg flac write is supported, will have to add this: */
2127 if(!test_level_2_misc_(/*is_ogg=*/true))