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 #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 <= 1200 /* @@@ [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"
47 /******************************************************************************
48 The general strategy of these tests (for interface levels 1 and 2) is
49 to create a dummy FLAC file with a known set of initial metadata
50 blocks, then keep a mirror locally of what we expect the metadata to be
51 after each operation. Then testing becomes a simple matter of running
52 a FLAC__StreamDecoder over the dummy file after each operation, comparing
53 the decoded metadata to what's in our local copy. If there are any
54 differences in the metadata, or the actual audio data is corrupted, we
55 will catch it while decoding.
56 ******************************************************************************/
59 FLAC__bool error_occurred;
60 } decoder_client_struct;
63 FLAC__StreamMetadata *blocks[64];
65 } our_metadata_struct;
67 /* our copy of the metadata in flacfilename() */
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 const char *flacfilename(FLAC__bool is_ogg)
75 return is_ogg? "metadata.ogg" : "metadata.flac";
78 static FLAC__bool die_(const char *msg)
80 printf("ERROR: %s\n", msg);
84 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
86 printf("ERROR: %s\n", msg);
87 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
91 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
93 printf("ERROR: %s\n", msg);
94 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
98 static void *malloc_or_die_(size_t size)
100 void *x = malloc(size);
102 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
108 static char *strdup_or_die_(const char *s)
112 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
118 /* functions for working with our metadata copy */
120 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
123 FLAC__StreamMetadata *obj = block;
124 FLAC__ASSERT(position < our_metadata_.num_blocks);
126 if(0 == (obj = FLAC__metadata_object_clone(block)))
127 return die_("during FLAC__metadata_object_clone()");
129 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
130 our_metadata_.blocks[position] = obj;
132 /* set the is_last flags */
133 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
134 our_metadata_.blocks[i]->is_last = false;
135 our_metadata_.blocks[i]->is_last = true;
140 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
143 FLAC__StreamMetadata *obj = block;
145 if(0 == (obj = FLAC__metadata_object_clone(block)))
146 return die_("during FLAC__metadata_object_clone()");
148 if(position > our_metadata_.num_blocks) {
149 position = our_metadata_.num_blocks;
152 for(i = our_metadata_.num_blocks; i > position; i--)
153 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
155 our_metadata_.blocks[position] = obj;
156 our_metadata_.num_blocks++;
158 /* set the is_last flags */
159 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
160 our_metadata_.blocks[i]->is_last = false;
161 our_metadata_.blocks[i]->is_last = true;
166 static void delete_from_our_metadata_(unsigned position)
169 FLAC__ASSERT(position < our_metadata_.num_blocks);
170 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
171 for(i = position; i < our_metadata_.num_blocks - 1; i++)
172 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
173 our_metadata_.num_blocks--;
175 /* set the is_last flags */
176 if(our_metadata_.num_blocks > 0) {
177 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
178 our_metadata_.blocks[i]->is_last = false;
179 our_metadata_.blocks[i]->is_last = true;
184 * This wad of functions supports filename- and callback-based chain reading/writing.
185 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
187 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
189 static const char *tempfile_suffix = ".metadata_edit";
191 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
193 strcpy(*tempfilename, filename);
194 strcat(*tempfilename, tempfile_suffix);
196 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
202 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
205 (void)fclose(*tempfile);
209 if(0 != *tempfilename) {
210 (void)unlink(*tempfilename);
216 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
218 FLAC__ASSERT(0 != filename);
219 FLAC__ASSERT(0 != tempfile);
220 FLAC__ASSERT(0 != tempfilename);
221 FLAC__ASSERT(0 != *tempfilename);
224 (void)fclose(*tempfile);
228 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
229 /* on some flavors of windows, rename() will fail if the destination already exists */
230 if(unlink(filename) < 0) {
231 cleanup_tempfile_(tempfile, tempfilename);
236 if(0 != rename(*tempfilename, filename)) {
237 cleanup_tempfile_(tempfile, tempfilename);
241 cleanup_tempfile_(tempfile, tempfilename);
246 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
248 FLAC__ASSERT(0 != filename);
249 FLAC__ASSERT(0 != stats);
250 return (0 == stat(filename, stats));
253 void set_file_stats_(const char *filename, struct stat *stats)
255 struct utimbuf srctime;
257 FLAC__ASSERT(0 != filename);
258 FLAC__ASSERT(0 != stats);
260 srctime.actime = stats->st_atime;
261 srctime.modtime = stats->st_mtime;
262 (void)chmod(filename, stats->st_mode);
263 (void)utime(filename, &srctime);
264 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
265 (void)chown(filename, stats->st_uid, -1);
266 (void)chown(filename, -1, stats->st_gid);
270 #ifdef FLAC__VALGRIND_TESTING
271 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
273 FILE *stream = (FILE*)handle;
274 size_t ret = fwrite(ptr, size, nmemb, stream);
281 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
283 off_t o = (off_t)offset;
284 FLAC__ASSERT(offset == o);
285 return fseeko((FILE*)handle, o, whence);
288 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
290 return ftello((FILE*)handle);
293 static int chain_eof_cb_(FLAC__IOHandle handle)
295 return feof((FILE*)handle);
298 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)
301 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
303 FLAC__IOCallbacks callbacks;
305 memset(&callbacks, 0, sizeof(callbacks));
306 callbacks.read = (FLAC__IOCallback_Read)fread;
307 #ifdef FLAC__VALGRIND_TESTING
308 callbacks.write = chain_write_cb_;
310 callbacks.write = (FLAC__IOCallback_Write)fwrite;
312 callbacks.seek = chain_seek_cb_;
313 callbacks.eof = chain_eof_cb_;
315 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
317 FILE *file, *tempfile;
319 if(preserve_file_stats) {
320 if(!get_file_stats_(filename, &stats))
323 if(0 == (file = fopen(filename, "rb")))
324 return false; /*@@@@ chain status still says OK though */
325 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
327 cleanup_tempfile_(&tempfile, &tempfilename);
328 return false; /*@@@@ chain status still says OK though */
330 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
338 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
340 if(preserve_file_stats)
341 set_file_stats_(filename, &stats);
344 FILE *file = fopen(filename, "r+b");
346 return false; /*@@@@ chain status still says OK though */
347 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
356 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based, FLAC__bool is_ogg)
360 FLAC__metadata_chain_read_ogg(chain, flacfilename(is_ogg)) :
361 FLAC__metadata_chain_read(chain, flacfilename(is_ogg))
364 FLAC__IOCallbacks callbacks;
366 memset(&callbacks, 0, sizeof(callbacks));
367 callbacks.read = (FLAC__IOCallback_Read)fread;
368 callbacks.seek = chain_seek_cb_;
369 callbacks.tell = chain_tell_cb_;
373 FILE *file = fopen(filename, "rb");
375 return false; /*@@@@ chain status still says OK though */
377 FLAC__metadata_chain_read_ogg_with_callbacks(chain, (FLAC__IOHandle)file, callbacks) :
378 FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)
386 /* function for comparing our metadata to a FLAC__Metadata_Chain */
388 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
391 FLAC__Metadata_Iterator *iterator;
392 FLAC__StreamMetadata *block;
393 FLAC__bool next_ok = true;
395 FLAC__ASSERT(0 != chain);
397 printf("\tcomparing chain... ");
400 if(0 == (iterator = FLAC__metadata_iterator_new()))
401 return die_("allocating memory for iterator");
403 FLAC__metadata_iterator_init(iterator, chain);
410 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
411 FLAC__metadata_iterator_delete(iterator);
412 return die_("getting block from iterator");
415 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
416 FLAC__metadata_iterator_delete(iterator);
417 return die_("metadata block mismatch");
421 next_ok = FLAC__metadata_iterator_next(iterator);
422 } while(i < our_metadata_.num_blocks && next_ok);
424 FLAC__metadata_iterator_delete(iterator);
427 return die_("chain has more blocks than expected");
429 if(i < our_metadata_.num_blocks)
430 return die_("short block count in chain");
432 if(0 != current_block) {
433 printf("CURRENT_POSITION... ");
436 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
437 return die_("metadata block mismatch");
445 /* decoder callbacks for checking the file */
447 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
449 (void)decoder, (void)buffer, (void)client_data;
452 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
453 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
455 printf("content... ");
459 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
462 /* this version pays no attention to the metadata */
463 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
465 (void)decoder, (void)metadata, (void)client_data;
467 printf("%d... ", mc_our_block_number_);
470 mc_our_block_number_++;
473 /* this version is used when we want to compare to our metadata copy */
474 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
476 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
480 /* don't bother checking if we've already hit an error */
481 if(dcd->error_occurred)
484 printf("%d... ", mc_our_block_number_);
487 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
488 (void)die_("got more metadata blocks than expected");
489 dcd->error_occurred = true;
492 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
493 (void)die_("metadata block mismatch");
494 dcd->error_occurred = true;
497 mc_our_block_number_++;
500 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
502 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
505 dcd->error_occurred = true;
506 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
509 static FLAC__bool generate_file_(FLAC__bool include_extras, FLAC__bool is_ogg)
511 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
512 FLAC__StreamMetadata *metadata[4];
513 unsigned i = 0, n = 0;
515 printf("generating %sFLAC file for test\n", is_ogg? "Ogg " : "");
517 while(our_metadata_.num_blocks > 0)
518 delete_from_our_metadata_(0);
520 streaminfo.is_last = false;
521 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
522 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
523 streaminfo.data.stream_info.min_blocksize = 576;
524 streaminfo.data.stream_info.max_blocksize = 576;
525 streaminfo.data.stream_info.min_framesize = 0;
526 streaminfo.data.stream_info.max_framesize = 0;
527 streaminfo.data.stream_info.sample_rate = 44100;
528 streaminfo.data.stream_info.channels = 1;
529 streaminfo.data.stream_info.bits_per_sample = 8;
530 streaminfo.data.stream_info.total_samples = 0;
531 memset(streaminfo.data.stream_info.md5sum, 0, 16);
534 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
535 vorbiscomment.is_last = false;
536 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
537 vorbiscomment.length = (4 + vendor_string_length) + 4;
538 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
539 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
540 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
541 vorbiscomment.data.vorbis_comment.num_comments = 0;
542 vorbiscomment.data.vorbis_comment.comments = 0;
546 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
547 return die_("priming our metadata");
548 cuesheet->is_last = false;
549 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
550 cuesheet->data.cue_sheet.lead_in = 123;
551 cuesheet->data.cue_sheet.is_cd = false;
552 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
553 return die_("priming our metadata");
554 cuesheet->data.cue_sheet.tracks[0].number = 1;
555 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
556 return die_("priming our metadata");
560 picture.is_last = false;
561 picture.type = FLAC__METADATA_TYPE_PICTURE;
564 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
565 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
566 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
567 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
568 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
569 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
570 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
571 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
574 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
575 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
576 picture.length += strlen(picture.data.picture.mime_type);
577 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
578 picture.length += strlen((const char *)picture.data.picture.description);
579 picture.data.picture.width = 300;
580 picture.data.picture.height = 300;
581 picture.data.picture.depth = 24;
582 picture.data.picture.colors = 0;
583 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
584 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
585 picture.length += picture.data.picture.data_length;
588 padding.is_last = true;
589 padding.type = FLAC__METADATA_TYPE_PADDING;
590 padding.length = 1234;
592 metadata[n++] = &vorbiscomment;
594 metadata[n++] = cuesheet;
595 metadata[n++] = &picture;
597 metadata[n++] = &padding;
600 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
601 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
602 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
603 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
604 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
606 return die_("priming our metadata");
608 if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), 0, 512 * 1024, &streaminfo, metadata, n))
609 return die_("creating the encoded file");
611 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
612 free(picture.data.picture.mime_type);
617 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
619 const char *filename = flacfilename(is_ogg);
620 FLAC__StreamDecoder *decoder;
621 decoder_client_struct decoder_client_data;
623 FLAC__ASSERT(0 != metadata_callback);
625 mc_our_block_number_ = 0;
626 decoder_client_data.error_occurred = false;
628 printf("\ttesting '%s'... ", filename);
631 if(0 == (decoder = FLAC__stream_decoder_new()))
632 return die_("couldn't allocate decoder instance");
634 FLAC__stream_decoder_set_md5_checking(decoder, true);
635 FLAC__stream_decoder_set_metadata_respond_all(decoder);
638 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
639 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
640 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
642 (void)FLAC__stream_decoder_finish(decoder);
643 FLAC__stream_decoder_delete(decoder);
644 return die_("initializing decoder\n");
646 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
647 (void)FLAC__stream_decoder_finish(decoder);
648 FLAC__stream_decoder_delete(decoder);
649 return die_("decoding file\n");
652 (void)FLAC__stream_decoder_finish(decoder);
653 FLAC__stream_decoder_delete(decoder);
655 if(decoder_client_data.error_occurred)
658 if(mc_our_block_number_ != our_metadata_.num_blocks)
659 return die_("short metadata block count");
665 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
667 if(!grabbag__file_change_stats(filename, read_only))
668 return die_("during grabbag__file_change_stats()");
673 static FLAC__bool remove_file_(const char *filename)
675 while(our_metadata_.num_blocks > 0)
676 delete_from_our_metadata_(0);
678 if(!grabbag__file_remove_file(filename))
679 return die_("removing file");
684 static FLAC__bool test_level_0_()
686 FLAC__StreamMetadata streaminfo;
687 FLAC__StreamMetadata *tags = 0;
688 FLAC__StreamMetadata *cuesheet = 0;
689 FLAC__StreamMetadata *picture = 0;
691 printf("\n\n++++++ testing level 0 interface\n");
693 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
696 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
699 printf("testing FLAC__metadata_get_streaminfo()... ");
701 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
702 return die_("during FLAC__metadata_get_streaminfo()");
704 /* check to see if some basic data matches (c.f. generate_file_()) */
705 if(streaminfo.data.stream_info.channels != 1)
706 return die_("mismatch in streaminfo.data.stream_info.channels");
707 if(streaminfo.data.stream_info.bits_per_sample != 8)
708 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
709 if(streaminfo.data.stream_info.sample_rate != 44100)
710 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
711 if(streaminfo.data.stream_info.min_blocksize != 576)
712 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
713 if(streaminfo.data.stream_info.max_blocksize != 576)
714 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
718 printf("testing FLAC__metadata_get_tags()... ");
720 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
721 return die_("during FLAC__metadata_get_tags()");
723 /* check to see if some basic data matches (c.f. generate_file_()) */
724 if(tags->data.vorbis_comment.num_comments != 0)
725 return die_("mismatch in tags->data.vorbis_comment.num_comments");
729 FLAC__metadata_object_delete(tags);
731 printf("testing FLAC__metadata_get_cuesheet()... ");
733 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
734 return die_("during FLAC__metadata_get_cuesheet()");
736 /* check to see if some basic data matches (c.f. generate_file_()) */
737 if(cuesheet->data.cue_sheet.lead_in != 123)
738 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
742 FLAC__metadata_object_delete(cuesheet);
744 printf("testing FLAC__metadata_get_picture()... ");
746 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)))
747 return die_("during FLAC__metadata_get_picture()");
749 /* check to see if some basic data matches (c.f. generate_file_()) */
750 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
751 return die_("mismatch in picture->data.picture.type");
755 FLAC__metadata_object_delete(picture);
757 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
763 static FLAC__bool test_level_1_()
765 FLAC__Metadata_SimpleIterator *iterator;
766 FLAC__StreamMetadata *block, *app, *padding;
767 FLAC__byte data[1000];
768 unsigned our_current_position = 0;
770 /* initialize 'data' to avoid Valgrind errors */
771 memset(data, 0, sizeof(data));
773 printf("\n\n++++++ testing level 1 interface\n");
775 /************************************************************/
777 printf("simple iterator on read-only file\n");
779 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
782 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
785 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
788 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
789 return die_("FLAC__metadata_simple_iterator_new()");
791 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
792 return die_("FLAC__metadata_simple_iterator_init() returned false");
794 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
795 if(FLAC__metadata_simple_iterator_is_writable(iterator))
796 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
798 printf("iterate forwards\n");
800 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
801 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
802 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
803 return die_("getting block 0");
804 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
805 return die_("expected STREAMINFO type");
807 return die_("expected is_last to be false");
808 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
809 return die_("bad STREAMINFO length");
810 /* check to see if some basic data matches (c.f. generate_file_()) */
811 if(block->data.stream_info.channels != 1)
812 return die_("mismatch in channels");
813 if(block->data.stream_info.bits_per_sample != 8)
814 return die_("mismatch in bits_per_sample");
815 if(block->data.stream_info.sample_rate != 44100)
816 return die_("mismatch in sample_rate");
817 if(block->data.stream_info.min_blocksize != 576)
818 return die_("mismatch in min_blocksize");
819 if(block->data.stream_info.max_blocksize != 576)
820 return die_("mismatch in max_blocksize");
821 FLAC__metadata_object_delete(block);
823 if(!FLAC__metadata_simple_iterator_next(iterator))
824 return die_("forward iterator ended early");
825 our_current_position++;
827 if(!FLAC__metadata_simple_iterator_next(iterator))
828 return die_("forward iterator ended early");
829 our_current_position++;
831 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
832 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
833 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
834 return die_("getting block 2");
835 if(block->type != FLAC__METADATA_TYPE_PADDING)
836 return die_("expected PADDING type");
838 return die_("expected is_last to be true");
839 /* check to see if some basic data matches (c.f. generate_file_()) */
840 if(block->length != 1234)
841 return die_("bad PADDING length");
842 FLAC__metadata_object_delete(block);
844 if(FLAC__metadata_simple_iterator_next(iterator))
845 return die_("forward iterator returned true but should have returned false");
847 printf("iterate backwards\n");
848 if(!FLAC__metadata_simple_iterator_prev(iterator))
849 return die_("reverse iterator ended early");
850 if(!FLAC__metadata_simple_iterator_prev(iterator))
851 return die_("reverse iterator ended early");
852 if(FLAC__metadata_simple_iterator_prev(iterator))
853 return die_("reverse iterator returned true but should have returned false");
855 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
857 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
858 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
860 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
862 FLAC__metadata_simple_iterator_delete(iterator);
864 /************************************************************/
866 printf("simple iterator on writable file\n");
868 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
871 printf("creating APPLICATION block\n");
873 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
874 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
875 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
877 printf("creating PADDING block\n");
879 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
880 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
881 padding->length = 20;
883 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
884 return die_("FLAC__metadata_simple_iterator_new()");
886 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
887 return die_("FLAC__metadata_simple_iterator_init() returned false");
888 our_current_position = 0;
890 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
892 printf("[S]VP\ttry to write over STREAMINFO block...\n");
893 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
894 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
896 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
898 printf("[S]VP\tnext\n");
899 if(!FLAC__metadata_simple_iterator_next(iterator))
900 return die_("iterator ended early\n");
901 our_current_position++;
903 printf("S[V]P\tnext\n");
904 if(!FLAC__metadata_simple_iterator_next(iterator))
905 return die_("iterator ended early\n");
906 our_current_position++;
908 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
909 padding->length = 25;
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 printf("SVP[P]\tprev\n");
916 if(!FLAC__metadata_simple_iterator_prev(iterator))
917 return die_("iterator ended early\n");
918 our_current_position--;
920 printf("SV[P]P\tprev\n");
921 if(!FLAC__metadata_simple_iterator_prev(iterator))
922 return die_("iterator ended early\n");
923 our_current_position--;
925 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
926 padding->length = 30;
927 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
928 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
929 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
932 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
935 printf("SV[P]PP\tprev\n");
936 if(!FLAC__metadata_simple_iterator_prev(iterator))
937 return die_("iterator ended early\n");
938 our_current_position--;
940 printf("S[V]PPP\tprev\n");
941 if(!FLAC__metadata_simple_iterator_prev(iterator))
942 return die_("iterator ended early\n");
943 our_current_position--;
945 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
946 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
947 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
949 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
952 printf("[S]VPPP\tnext\n");
953 if(!FLAC__metadata_simple_iterator_next(iterator))
954 return die_("iterator ended early\n");
955 our_current_position++;
957 printf("S[V]PPP\tnext\n");
958 if(!FLAC__metadata_simple_iterator_next(iterator))
959 return die_("iterator ended early\n");
960 our_current_position++;
962 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
963 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
964 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
965 our_current_position--;
967 printf("S[V]PPP\tnext\n");
968 if(!FLAC__metadata_simple_iterator_next(iterator))
969 return die_("iterator ended early\n");
970 our_current_position++;
972 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
973 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
974 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
975 delete_from_our_metadata_(our_current_position--);
977 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
980 printf("S[V]PP\tnext\n");
981 if(!FLAC__metadata_simple_iterator_next(iterator))
982 return die_("iterator ended early\n");
983 our_current_position++;
985 printf("SV[P]P\tnext\n");
986 if(!FLAC__metadata_simple_iterator_next(iterator))
987 return die_("iterator ended early\n");
988 our_current_position++;
990 printf("SVP[P]\tdelete (last block), replace with padding\n");
991 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
992 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
993 our_current_position--;
995 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
998 printf("SV[P]P\tnext\n");
999 if(!FLAC__metadata_simple_iterator_next(iterator))
1000 return die_("iterator ended early\n");
1001 our_current_position++;
1003 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1004 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1005 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1006 delete_from_our_metadata_(our_current_position--);
1008 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1011 printf("SV[P]\tprev\n");
1012 if(!FLAC__metadata_simple_iterator_prev(iterator))
1013 return die_("iterator ended early\n");
1014 our_current_position--;
1016 printf("S[V]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]VP\tset STREAMINFO (change sample rate)\n");
1022 FLAC__ASSERT(our_current_position == 0);
1023 block = FLAC__metadata_simple_iterator_get_block(iterator);
1024 block->data.stream_info.sample_rate = 32000;
1025 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1026 return die_("copying object");
1027 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1028 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1029 FLAC__metadata_object_delete(block);
1031 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1034 printf("[S]VP\tnext\n");
1035 if(!FLAC__metadata_simple_iterator_next(iterator))
1036 return die_("iterator ended early\n");
1037 our_current_position++;
1039 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1040 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1041 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1042 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1043 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1045 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1047 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1050 printf("SV[A]P\tnext\n");
1051 if(!FLAC__metadata_simple_iterator_next(iterator))
1052 return die_("iterator ended early\n");
1053 our_current_position++;
1055 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1056 app->data.application.id[0] = 'f'; /* twiddle the id */
1057 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1058 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1059 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1061 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1063 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1066 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1067 app->data.application.id[0] = 'g'; /* twiddle the id */
1068 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1069 return die_("setting APPLICATION data");
1070 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1071 return die_("copying object");
1072 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1073 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1075 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1078 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1079 app->data.application.id[0] = 'h'; /* twiddle the id */
1080 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1081 return die_("setting APPLICATION data");
1082 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1083 return die_("copying object");
1084 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1085 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1087 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1090 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1091 app->data.application.id[0] = 'i'; /* twiddle the id */
1092 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1093 return die_("setting APPLICATION data");
1094 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1095 return die_("copying object");
1096 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1097 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1098 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1100 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1103 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1104 app->data.application.id[0] = 'j'; /* twiddle the id */
1105 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1106 return die_("setting APPLICATION data");
1107 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1108 return die_("copying object");
1109 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1110 return die_("copying object");
1111 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1112 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1113 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1115 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1118 printf("SVA[A]PP\tnext\n");
1119 if(!FLAC__metadata_simple_iterator_next(iterator))
1120 return die_("iterator ended early\n");
1121 our_current_position++;
1123 printf("SVAA[P]P\tnext\n");
1124 if(!FLAC__metadata_simple_iterator_next(iterator))
1125 return die_("iterator ended early\n");
1126 our_current_position++;
1128 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1129 padding->length = 5;
1130 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1131 return die_("copying object");
1132 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1133 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1135 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1138 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1139 app->data.application.id[0] = 'k'; /* twiddle the id */
1140 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1141 return die_("copying object");
1142 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1143 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1145 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1148 printf("SVAAP[A]\tset PADDING (equal)\n");
1149 padding->length = 27;
1150 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1151 return die_("copying object");
1152 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1153 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1155 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1158 printf("SVAAP[P]\tprev\n");
1159 if(!FLAC__metadata_simple_iterator_prev(iterator))
1160 return die_("iterator ended early\n");
1161 our_current_position--;
1163 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1164 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1165 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1166 delete_from_our_metadata_(our_current_position--);
1168 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1171 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1172 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1173 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1174 delete_from_our_metadata_(our_current_position--);
1176 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1179 printf("SV[A]P\tnext\n");
1180 if(!FLAC__metadata_simple_iterator_next(iterator))
1181 return die_("iterator ended early\n");
1182 our_current_position++;
1184 printf("SVA[P]\tinsert PADDING after\n");
1185 padding->length = 5;
1186 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1187 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1188 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1191 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1194 printf("SVAP[P]\tprev\n");
1195 if(!FLAC__metadata_simple_iterator_prev(iterator))
1196 return die_("iterator ended early\n");
1197 our_current_position--;
1199 printf("SVA[P]P\tprev\n");
1200 if(!FLAC__metadata_simple_iterator_prev(iterator))
1201 return die_("iterator ended early\n");
1202 our_current_position--;
1204 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1205 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1206 return die_("setting APPLICATION data");
1207 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1208 return die_("copying object");
1209 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1210 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1212 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1215 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1216 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1217 return die_("setting APPLICATION data");
1218 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1219 return die_("copying object");
1220 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1221 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1223 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1226 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1227 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1228 return die_("setting APPLICATION data");
1229 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1230 return die_("copying object");
1231 our_metadata_.blocks[our_current_position+1]->length = 0;
1232 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1233 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1235 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1238 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1239 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1240 return die_("setting APPLICATION data");
1241 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1242 return die_("copying object");
1243 delete_from_our_metadata_(our_current_position+1);
1244 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1245 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1247 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1250 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1251 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1252 return die_("setting APPLICATION data");
1253 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1254 return die_("copying object");
1255 delete_from_our_metadata_(our_current_position+1);
1256 our_metadata_.blocks[our_current_position]->is_last = true;
1257 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1258 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1260 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1263 printf("SV[A]\tset PADDING (equal size)\n");
1264 padding->length = app->length;
1265 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1266 return die_("copying object");
1267 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1268 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1270 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1273 printf("SV[P]\tinsert PADDING after\n");
1274 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1275 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1276 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1279 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1282 printf("SVP[P]\tinsert PADDING after\n");
1283 padding->length = 5;
1284 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1285 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1286 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1289 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1292 printf("SVPP[P]\tprev\n");
1293 if(!FLAC__metadata_simple_iterator_prev(iterator))
1294 return die_("iterator ended early\n");
1295 our_current_position--;
1297 printf("SVP[P]P\tprev\n");
1298 if(!FLAC__metadata_simple_iterator_prev(iterator))
1299 return die_("iterator ended early\n");
1300 our_current_position--;
1302 printf("SV[P]PP\tprev\n");
1303 if(!FLAC__metadata_simple_iterator_prev(iterator))
1304 return die_("iterator ended early\n");
1305 our_current_position--;
1307 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1308 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1309 return die_("setting APPLICATION data");
1310 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1311 return die_("copying object");
1312 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1313 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1315 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1318 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1319 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1320 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1321 delete_from_our_metadata_(our_current_position--);
1323 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1326 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1327 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1328 return die_("setting APPLICATION data");
1329 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1330 return die_("copying object");
1331 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1332 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1334 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1337 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1338 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1339 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1340 delete_from_our_metadata_(our_current_position--);
1342 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1345 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1346 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1347 return die_("setting APPLICATION data");
1348 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1349 return die_("copying object");
1350 delete_from_our_metadata_(our_current_position+1);
1351 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1352 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1354 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1357 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1358 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1359 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1360 delete_from_our_metadata_(our_current_position--);
1362 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1365 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1366 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1367 return die_("setting APPLICATION data");
1368 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1369 return die_("copying object");
1370 our_metadata_.blocks[our_current_position+1]->length = 0;
1371 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1372 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1374 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1377 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1378 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1379 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1380 delete_from_our_metadata_(our_current_position--);
1382 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1385 printf("S[V]PP\tnext\n");
1386 if(!FLAC__metadata_simple_iterator_next(iterator))
1387 return die_("iterator ended early\n");
1388 our_current_position++;
1390 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1391 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1392 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1393 delete_from_our_metadata_(our_current_position--);
1395 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1398 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1399 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1400 return die_("setting APPLICATION data");
1401 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1402 return die_("copying object");
1403 delete_from_our_metadata_(our_current_position+1);
1404 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1405 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1407 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1410 printf("delete simple iterator\n");
1412 FLAC__metadata_simple_iterator_delete(iterator);
1414 FLAC__metadata_object_delete(app);
1415 FLAC__metadata_object_delete(padding);
1417 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1423 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1425 FLAC__Metadata_Iterator *iterator;
1426 FLAC__Metadata_Chain *chain;
1427 FLAC__StreamMetadata *block, *app, *padding;
1428 FLAC__byte data[2000];
1429 unsigned our_current_position;
1431 /* initialize 'data' to avoid Valgrind errors */
1432 memset(data, 0, sizeof(data));
1434 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1436 printf("generate read-only file\n");
1438 if(!generate_file_(/*include_extras=*/false, is_ogg))
1441 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1444 printf("create chain\n");
1446 if(0 == (chain = FLAC__metadata_chain_new()))
1447 return die_("allocating chain");
1449 printf("read chain\n");
1451 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1452 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1454 printf("[S]VP\ttest initial metadata\n");
1456 if(!compare_chain_(chain, 0, 0))
1458 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1464 printf("switch file to read-write\n");
1466 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1469 printf("create iterator\n");
1470 if(0 == (iterator = FLAC__metadata_iterator_new()))
1471 return die_("allocating memory for iterator");
1473 our_current_position = 0;
1475 FLAC__metadata_iterator_init(iterator, chain);
1477 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1478 return die_("getting block from iterator");
1480 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1482 printf("[S]VP\tmodify STREAMINFO, write\n");
1484 block->data.stream_info.sample_rate = 32000;
1485 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1486 return die_("copying object");
1488 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1489 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1490 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1492 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1495 printf("[S]VP\tnext\n");
1496 if(!FLAC__metadata_iterator_next(iterator))
1497 return die_("iterator ended early\n");
1498 our_current_position++;
1500 printf("S[V]P\tnext\n");
1501 if(!FLAC__metadata_iterator_next(iterator))
1502 return die_("iterator ended early\n");
1503 our_current_position++;
1505 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1506 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1507 return die_("getting block from iterator");
1508 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1509 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1510 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1511 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1512 return die_("setting APPLICATION data");
1513 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1514 return die_("copying object");
1515 if(!FLAC__metadata_iterator_set_block(iterator, app))
1516 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1518 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1519 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1520 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1522 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1525 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1526 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1527 return die_("copying object");
1528 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1529 return die_("setting APPLICATION data");
1530 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1531 return die_("copying object");
1532 if(!FLAC__metadata_iterator_set_block(iterator, app))
1533 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1535 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1536 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1537 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1539 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1542 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1543 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1544 return die_("copying object");
1545 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1546 return die_("setting APPLICATION data");
1547 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1548 return die_("copying object");
1549 if(!FLAC__metadata_iterator_set_block(iterator, app))
1550 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1552 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1553 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1554 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1556 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1559 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1560 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1561 return die_("copying object");
1562 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1563 return die_("setting APPLICATION data");
1564 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1565 return die_("copying object");
1566 if(!FLAC__metadata_iterator_set_block(iterator, app))
1567 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1569 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1570 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1571 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1573 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1576 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1577 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1578 return die_("copying object");
1579 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1580 return die_("setting APPLICATION data");
1581 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1582 return die_("copying object");
1583 if(!FLAC__metadata_iterator_set_block(iterator, app))
1584 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1586 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1587 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1588 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1590 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1593 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1594 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1595 return die_("creating PADDING block");
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, 29, 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 padding->length = 0;
1603 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1604 return die_("internal error");
1605 if(!FLAC__metadata_iterator_set_block(iterator, app))
1606 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1608 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1609 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1610 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1612 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1615 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1616 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1617 return die_("copying object");
1618 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1619 return die_("setting APPLICATION data");
1620 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1621 return die_("copying object");
1622 our_metadata_.blocks[our_current_position+1]->length = 13;
1623 if(!FLAC__metadata_iterator_set_block(iterator, app))
1624 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1626 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1627 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1628 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1630 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1633 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1634 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1635 return die_("copying object");
1636 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1637 return die_("setting APPLICATION data");
1638 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1639 return die_("copying object");
1640 if(!FLAC__metadata_iterator_set_block(iterator, app))
1641 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1643 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1644 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1645 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1647 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1650 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1651 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1652 return die_("copying object");
1653 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1654 return die_("setting APPLICATION data");
1655 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1656 return die_("copying object");
1657 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1658 if(!FLAC__metadata_iterator_set_block(iterator, app))
1659 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1661 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1662 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1663 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1665 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1668 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1669 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1670 return die_("copying object");
1671 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1672 return die_("setting APPLICATION data");
1673 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1674 return die_("copying object");
1675 delete_from_our_metadata_(our_current_position+1);
1676 if(!FLAC__metadata_iterator_set_block(iterator, app))
1677 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1679 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1680 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1681 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1683 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1686 printf("SV[A]\tprev\n");
1687 if(!FLAC__metadata_iterator_prev(iterator))
1688 return die_("iterator ended early\n");
1689 our_current_position--;
1691 printf("S[V]A\tprev\n");
1692 if(!FLAC__metadata_iterator_prev(iterator))
1693 return die_("iterator ended early\n");
1694 our_current_position--;
1696 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1697 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1698 return die_("creating PADDING block");
1699 padding->length = 30;
1700 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1701 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1703 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1705 printf("[S]VP\tnext\n");
1706 if(!FLAC__metadata_iterator_next(iterator))
1707 return die_("iterator ended early\n");
1708 our_current_position++;
1710 printf("S[V]A\tinsert PADDING after\n");
1711 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1712 return die_("copying metadata");
1713 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1714 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1716 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1719 printf("SV[P]A\tinsert PADDING before\n");
1720 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1721 return die_("creating PADDING block");
1722 padding->length = 17;
1723 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1724 return die_("copying metadata");
1725 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1726 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1728 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1731 printf("SV[P]PA\tinsert PADDING before\n");
1732 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1733 return die_("creating PADDING block");
1734 padding->length = 0;
1735 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1736 return die_("copying metadata");
1737 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1738 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1740 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1743 printf("SV[P]PPA\tnext\n");
1744 if(!FLAC__metadata_iterator_next(iterator))
1745 return die_("iterator ended early\n");
1746 our_current_position++;
1748 printf("SVP[P]PA\tnext\n");
1749 if(!FLAC__metadata_iterator_next(iterator))
1750 return die_("iterator ended early\n");
1751 our_current_position++;
1753 printf("SVPP[P]A\tnext\n");
1754 if(!FLAC__metadata_iterator_next(iterator))
1755 return die_("iterator ended early\n");
1756 our_current_position++;
1758 printf("SVPPP[A]\tinsert PADDING after\n");
1759 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1760 return die_("creating PADDING block");
1761 padding->length = 57;
1762 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1763 return die_("copying metadata");
1764 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1765 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1767 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1770 printf("SVPPPA[P]\tinsert PADDING before\n");
1771 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1772 return die_("creating PADDING block");
1773 padding->length = 99;
1774 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1775 return die_("copying metadata");
1776 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1777 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1779 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1782 printf("delete iterator\n");
1783 FLAC__metadata_iterator_delete(iterator);
1784 our_current_position = 0;
1786 printf("SVPPPAPP\tmerge padding\n");
1787 FLAC__metadata_chain_merge_padding(chain);
1788 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1789 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1790 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1791 delete_from_our_metadata_(7);
1792 delete_from_our_metadata_(4);
1793 delete_from_our_metadata_(3);
1795 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1796 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1797 if(!compare_chain_(chain, 0, 0))
1799 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1802 printf("SVPAP\tsort padding\n");
1803 FLAC__metadata_chain_sort_padding(chain);
1804 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1805 delete_from_our_metadata_(2);
1807 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1808 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1809 if(!compare_chain_(chain, 0, 0))
1811 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1814 printf("create iterator\n");
1815 if(0 == (iterator = FLAC__metadata_iterator_new()))
1816 return die_("allocating memory for iterator");
1818 our_current_position = 0;
1820 FLAC__metadata_iterator_init(iterator, chain);
1822 printf("[S]VAP\tnext\n");
1823 if(!FLAC__metadata_iterator_next(iterator))
1824 return die_("iterator ended early\n");
1825 our_current_position++;
1827 printf("S[V]AP\tnext\n");
1828 if(!FLAC__metadata_iterator_next(iterator))
1829 return die_("iterator ended early\n");
1830 our_current_position++;
1832 printf("SV[A]P\tdelete middle block, replace with padding\n");
1833 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1834 return die_("creating PADDING block");
1835 padding->length = 71;
1836 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1837 return die_("copying object");
1838 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1839 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1841 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1844 printf("S[V]PP\tnext\n");
1845 if(!FLAC__metadata_iterator_next(iterator))
1846 return die_("iterator ended early\n");
1847 our_current_position++;
1849 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1850 delete_from_our_metadata_(our_current_position--);
1851 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1852 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1854 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1857 printf("S[V]P\tnext\n");
1858 if(!FLAC__metadata_iterator_next(iterator))
1859 return die_("iterator ended early\n");
1860 our_current_position++;
1862 printf("SV[P]\tdelete last block, replace with padding\n");
1863 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1864 return die_("creating PADDING block");
1865 padding->length = 219;
1866 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1867 return die_("copying object");
1868 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1869 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1871 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1874 printf("S[V]P\tnext\n");
1875 if(!FLAC__metadata_iterator_next(iterator))
1876 return die_("iterator ended early\n");
1877 our_current_position++;
1879 printf("SV[P]\tdelete last block, don't replace with padding\n");
1880 delete_from_our_metadata_(our_current_position--);
1881 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1882 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1884 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1887 printf("S[V]\tprev\n");
1888 if(!FLAC__metadata_iterator_prev(iterator))
1889 return die_("iterator ended early\n");
1890 our_current_position--;
1892 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1893 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1894 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1896 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1899 printf("delete iterator\n");
1900 FLAC__metadata_iterator_delete(iterator);
1901 our_current_position = 0;
1903 printf("SV\tmerge padding\n");
1904 FLAC__metadata_chain_merge_padding(chain);
1906 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1907 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1908 if(!compare_chain_(chain, 0, 0))
1910 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1913 printf("SV\tsort padding\n");
1914 FLAC__metadata_chain_sort_padding(chain);
1916 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1917 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1918 if(!compare_chain_(chain, 0, 0))
1920 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1924 printf("delete chain\n");
1926 FLAC__metadata_chain_delete(chain);
1928 if(!remove_file_(flacfilename(is_ogg)))
1934 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1936 FLAC__Metadata_Iterator *iterator;
1937 FLAC__Metadata_Chain *chain;
1938 FLAC__IOCallbacks callbacks;
1940 memset(&callbacks, 0, sizeof(callbacks));
1941 callbacks.read = (FLAC__IOCallback_Read)fread;
1942 #ifdef FLAC__VALGRIND_TESTING
1943 callbacks.write = chain_write_cb_;
1945 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1947 callbacks.seek = chain_seek_cb_;
1948 callbacks.tell = chain_tell_cb_;
1949 callbacks.eof = chain_eof_cb_;
1951 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1953 printf("generate file\n");
1955 if(!generate_file_(/*include_extras=*/false, is_ogg))
1958 printf("create chain\n");
1960 if(0 == (chain = FLAC__metadata_chain_new()))
1961 return die_("allocating chain");
1963 printf("read chain (filename-based)\n");
1965 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1966 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1968 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1970 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1971 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1972 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1973 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1974 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1977 printf("read chain (filename-based)\n");
1979 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1980 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1982 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1984 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
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_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1991 printf("read chain (callback-based)\n");
1993 FILE *file = fopen(flacfilename(is_ogg), "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("write chain with wrong method FLAC__metadata_chain_write()\n");
2005 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2006 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2007 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2008 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2009 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2012 printf("read chain (callback-based)\n");
2014 FILE *file = fopen(flacfilename(is_ogg), "rb");
2016 return die_("opening file");
2017 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2019 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2024 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2026 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2027 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2029 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2031 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2033 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2034 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2035 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2036 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2037 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2040 printf("read chain (callback-based)\n");
2042 FILE *file = fopen(flacfilename(is_ogg), "rb");
2044 return die_("opening file");
2045 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2047 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2052 printf("create iterator\n");
2053 if(0 == (iterator = FLAC__metadata_iterator_new()))
2054 return die_("allocating memory for iterator");
2056 FLAC__metadata_iterator_init(iterator, chain);
2058 printf("[S]VP\tnext\n");
2059 if(!FLAC__metadata_iterator_next(iterator))
2060 return die_("iterator ended early\n");
2062 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2063 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2064 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2066 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2068 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2069 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2071 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2073 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2075 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2076 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2077 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2078 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2079 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2082 printf("delete iterator\n");
2084 FLAC__metadata_iterator_delete(iterator);
2086 printf("delete chain\n");
2088 FLAC__metadata_chain_delete(chain);
2090 if(!remove_file_(flacfilename(is_ogg)))
2096 FLAC__bool test_metadata_file_manipulation()
2098 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2100 our_metadata_.num_blocks = 0;
2102 if(!test_level_0_())
2105 if(!test_level_1_())
2108 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2110 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2112 if(!test_level_2_misc_(/*is_ogg=*/false))
2115 if(FLAC_API_SUPPORTS_OGG_FLAC) {
2116 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2118 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2121 /* when ogg flac write is supported, will have to add this: */
2122 if(!test_level_2_misc_(/*is_ogg=*/true))