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"
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);
613 free(picture.data.picture.description);
614 free(picture.data.picture.data);
616 FLAC__metadata_object_delete(cuesheet);
621 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
623 const char *filename = flacfilename(is_ogg);
624 FLAC__StreamDecoder *decoder;
625 decoder_client_struct decoder_client_data;
627 FLAC__ASSERT(0 != metadata_callback);
629 mc_our_block_number_ = 0;
630 decoder_client_data.error_occurred = false;
632 printf("\ttesting '%s'... ", filename);
635 if(0 == (decoder = FLAC__stream_decoder_new()))
636 return die_("couldn't allocate decoder instance");
638 FLAC__stream_decoder_set_md5_checking(decoder, true);
639 FLAC__stream_decoder_set_metadata_respond_all(decoder);
642 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
643 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
644 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
646 (void)FLAC__stream_decoder_finish(decoder);
647 FLAC__stream_decoder_delete(decoder);
648 return die_("initializing decoder\n");
650 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
651 (void)FLAC__stream_decoder_finish(decoder);
652 FLAC__stream_decoder_delete(decoder);
653 return die_("decoding file\n");
656 (void)FLAC__stream_decoder_finish(decoder);
657 FLAC__stream_decoder_delete(decoder);
659 if(decoder_client_data.error_occurred)
662 if(mc_our_block_number_ != our_metadata_.num_blocks)
663 return die_("short metadata block count");
669 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
671 if(!grabbag__file_change_stats(filename, read_only))
672 return die_("during grabbag__file_change_stats()");
677 static FLAC__bool remove_file_(const char *filename)
679 while(our_metadata_.num_blocks > 0)
680 delete_from_our_metadata_(0);
682 if(!grabbag__file_remove_file(filename))
683 return die_("removing file");
688 static FLAC__bool test_level_0_(void)
690 FLAC__StreamMetadata streaminfo;
691 FLAC__StreamMetadata *tags = 0;
692 FLAC__StreamMetadata *cuesheet = 0;
693 FLAC__StreamMetadata *picture = 0;
695 printf("\n\n++++++ testing level 0 interface\n");
697 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
700 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
703 printf("testing FLAC__metadata_get_streaminfo()... ");
705 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
706 return die_("during FLAC__metadata_get_streaminfo()");
708 /* check to see if some basic data matches (c.f. generate_file_()) */
709 if(streaminfo.data.stream_info.channels != 1)
710 return die_("mismatch in streaminfo.data.stream_info.channels");
711 if(streaminfo.data.stream_info.bits_per_sample != 8)
712 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
713 if(streaminfo.data.stream_info.sample_rate != 44100)
714 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
715 if(streaminfo.data.stream_info.min_blocksize != 576)
716 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
717 if(streaminfo.data.stream_info.max_blocksize != 576)
718 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
722 printf("testing FLAC__metadata_get_tags()... ");
724 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
725 return die_("during FLAC__metadata_get_tags()");
727 /* check to see if some basic data matches (c.f. generate_file_()) */
728 if(tags->data.vorbis_comment.num_comments != 0)
729 return die_("mismatch in tags->data.vorbis_comment.num_comments");
733 FLAC__metadata_object_delete(tags);
735 printf("testing FLAC__metadata_get_cuesheet()... ");
737 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
738 return die_("during FLAC__metadata_get_cuesheet()");
740 /* check to see if some basic data matches (c.f. generate_file_()) */
741 if(cuesheet->data.cue_sheet.lead_in != 123)
742 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
746 FLAC__metadata_object_delete(cuesheet);
748 printf("testing FLAC__metadata_get_picture()... ");
750 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)))
751 return die_("during FLAC__metadata_get_picture()");
753 /* check to see if some basic data matches (c.f. generate_file_()) */
754 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
755 return die_("mismatch in picture->data.picture.type");
759 FLAC__metadata_object_delete(picture);
761 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
767 static FLAC__bool test_level_1_(void)
769 FLAC__Metadata_SimpleIterator *iterator;
770 FLAC__StreamMetadata *block, *app, *padding;
771 FLAC__byte data[1000];
772 unsigned our_current_position = 0;
774 /* initialize 'data' to avoid Valgrind errors */
775 memset(data, 0, sizeof(data));
777 printf("\n\n++++++ testing level 1 interface\n");
779 /************************************************************/
781 printf("simple iterator on read-only file\n");
783 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
786 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
789 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
792 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
793 return die_("FLAC__metadata_simple_iterator_new()");
795 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
796 return die_("FLAC__metadata_simple_iterator_init() returned false");
798 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
799 if(FLAC__metadata_simple_iterator_is_writable(iterator))
800 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
802 printf("iterate forwards\n");
804 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
805 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
806 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
807 return die_("getting block 0");
808 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
809 return die_("expected STREAMINFO type");
811 return die_("expected is_last to be false");
812 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
813 return die_("bad STREAMINFO length");
814 /* check to see if some basic data matches (c.f. generate_file_()) */
815 if(block->data.stream_info.channels != 1)
816 return die_("mismatch in channels");
817 if(block->data.stream_info.bits_per_sample != 8)
818 return die_("mismatch in bits_per_sample");
819 if(block->data.stream_info.sample_rate != 44100)
820 return die_("mismatch in sample_rate");
821 if(block->data.stream_info.min_blocksize != 576)
822 return die_("mismatch in min_blocksize");
823 if(block->data.stream_info.max_blocksize != 576)
824 return die_("mismatch in max_blocksize");
825 FLAC__metadata_object_delete(block);
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_next(iterator))
832 return die_("forward iterator ended early");
833 our_current_position++;
835 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
836 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
837 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
838 return die_("getting block 2");
839 if(block->type != FLAC__METADATA_TYPE_PADDING)
840 return die_("expected PADDING type");
842 return die_("expected is_last to be true");
843 /* check to see if some basic data matches (c.f. generate_file_()) */
844 if(block->length != 1234)
845 return die_("bad PADDING length");
846 FLAC__metadata_object_delete(block);
848 if(FLAC__metadata_simple_iterator_next(iterator))
849 return die_("forward iterator returned true but should have returned false");
851 printf("iterate backwards\n");
852 if(!FLAC__metadata_simple_iterator_prev(iterator))
853 return die_("reverse iterator ended early");
854 if(!FLAC__metadata_simple_iterator_prev(iterator))
855 return die_("reverse iterator ended early");
856 if(FLAC__metadata_simple_iterator_prev(iterator))
857 return die_("reverse iterator returned true but should have returned false");
859 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
861 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
862 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
864 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
866 FLAC__metadata_simple_iterator_delete(iterator);
868 /************************************************************/
870 printf("simple iterator on writable file\n");
872 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
875 printf("creating APPLICATION block\n");
877 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
878 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
879 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
881 printf("creating PADDING block\n");
883 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
884 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
885 padding->length = 20;
887 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
888 return die_("FLAC__metadata_simple_iterator_new()");
890 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
891 return die_("FLAC__metadata_simple_iterator_init() returned false");
892 our_current_position = 0;
894 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
896 printf("[S]VP\ttry to write over STREAMINFO block...\n");
897 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
898 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
900 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
902 printf("[S]VP\tnext\n");
903 if(!FLAC__metadata_simple_iterator_next(iterator))
904 return die_("iterator ended early\n");
905 our_current_position++;
907 printf("S[V]P\tnext\n");
908 if(!FLAC__metadata_simple_iterator_next(iterator))
909 return die_("iterator ended early\n");
910 our_current_position++;
912 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
913 padding->length = 25;
914 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
915 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
916 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
919 printf("SVP[P]\tprev\n");
920 if(!FLAC__metadata_simple_iterator_prev(iterator))
921 return die_("iterator ended early\n");
922 our_current_position--;
924 printf("SV[P]P\tprev\n");
925 if(!FLAC__metadata_simple_iterator_prev(iterator))
926 return die_("iterator ended early\n");
927 our_current_position--;
929 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
930 padding->length = 30;
931 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
932 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
933 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
936 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
939 printf("SV[P]PP\tprev\n");
940 if(!FLAC__metadata_simple_iterator_prev(iterator))
941 return die_("iterator ended early\n");
942 our_current_position--;
944 printf("S[V]PPP\tprev\n");
945 if(!FLAC__metadata_simple_iterator_prev(iterator))
946 return die_("iterator ended early\n");
947 our_current_position--;
949 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
950 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
951 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
953 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
956 printf("[S]VPPP\tnext\n");
957 if(!FLAC__metadata_simple_iterator_next(iterator))
958 return die_("iterator ended early\n");
959 our_current_position++;
961 printf("S[V]PPP\tnext\n");
962 if(!FLAC__metadata_simple_iterator_next(iterator))
963 return die_("iterator ended early\n");
964 our_current_position++;
966 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
967 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
968 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
969 our_current_position--;
971 printf("S[V]PPP\tnext\n");
972 if(!FLAC__metadata_simple_iterator_next(iterator))
973 return die_("iterator ended early\n");
974 our_current_position++;
976 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
977 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
978 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
979 delete_from_our_metadata_(our_current_position--);
981 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
984 printf("S[V]PP\tnext\n");
985 if(!FLAC__metadata_simple_iterator_next(iterator))
986 return die_("iterator ended early\n");
987 our_current_position++;
989 printf("SV[P]P\tnext\n");
990 if(!FLAC__metadata_simple_iterator_next(iterator))
991 return die_("iterator ended early\n");
992 our_current_position++;
994 printf("SVP[P]\tdelete (last block), replace with padding\n");
995 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
996 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
997 our_current_position--;
999 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1002 printf("SV[P]P\tnext\n");
1003 if(!FLAC__metadata_simple_iterator_next(iterator))
1004 return die_("iterator ended early\n");
1005 our_current_position++;
1007 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1008 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1009 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1010 delete_from_our_metadata_(our_current_position--);
1012 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1015 printf("SV[P]\tprev\n");
1016 if(!FLAC__metadata_simple_iterator_prev(iterator))
1017 return die_("iterator ended early\n");
1018 our_current_position--;
1020 printf("S[V]P\tprev\n");
1021 if(!FLAC__metadata_simple_iterator_prev(iterator))
1022 return die_("iterator ended early\n");
1023 our_current_position--;
1025 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1026 FLAC__ASSERT(our_current_position == 0);
1027 block = FLAC__metadata_simple_iterator_get_block(iterator);
1028 block->data.stream_info.sample_rate = 32000;
1029 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1030 return die_("copying object");
1031 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1032 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1033 FLAC__metadata_object_delete(block);
1035 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1038 printf("[S]VP\tnext\n");
1039 if(!FLAC__metadata_simple_iterator_next(iterator))
1040 return die_("iterator ended early\n");
1041 our_current_position++;
1043 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1044 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1045 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1046 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1047 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1049 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1051 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1054 printf("SV[A]P\tnext\n");
1055 if(!FLAC__metadata_simple_iterator_next(iterator))
1056 return die_("iterator ended early\n");
1057 our_current_position++;
1059 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1060 app->data.application.id[0] = 'f'; /* twiddle the id */
1061 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1062 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1063 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1065 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1067 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1070 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1071 app->data.application.id[0] = 'g'; /* twiddle the id */
1072 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1073 return die_("setting APPLICATION data");
1074 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1075 return die_("copying object");
1076 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1077 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1079 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1082 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1083 app->data.application.id[0] = 'h'; /* twiddle the id */
1084 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1085 return die_("setting APPLICATION data");
1086 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1087 return die_("copying object");
1088 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1089 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1091 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1094 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1095 app->data.application.id[0] = 'i'; /* twiddle the id */
1096 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1097 return die_("setting APPLICATION data");
1098 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1099 return die_("copying object");
1100 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1101 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1102 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1104 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1107 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1108 app->data.application.id[0] = 'j'; /* twiddle the id */
1109 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1110 return die_("setting APPLICATION data");
1111 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1112 return die_("copying object");
1113 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1114 return die_("copying object");
1115 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1116 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1117 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1119 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1122 printf("SVA[A]PP\tnext\n");
1123 if(!FLAC__metadata_simple_iterator_next(iterator))
1124 return die_("iterator ended early\n");
1125 our_current_position++;
1127 printf("SVAA[P]P\tnext\n");
1128 if(!FLAC__metadata_simple_iterator_next(iterator))
1129 return die_("iterator ended early\n");
1130 our_current_position++;
1132 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1133 padding->length = 5;
1134 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1135 return die_("copying object");
1136 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1137 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1139 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1142 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1143 app->data.application.id[0] = 'k'; /* twiddle the id */
1144 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1145 return die_("copying object");
1146 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1147 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1149 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1152 printf("SVAAP[A]\tset PADDING (equal)\n");
1153 padding->length = 27;
1154 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1155 return die_("copying object");
1156 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1157 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1159 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1162 printf("SVAAP[P]\tprev\n");
1163 if(!FLAC__metadata_simple_iterator_prev(iterator))
1164 return die_("iterator ended early\n");
1165 our_current_position--;
1167 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1168 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1169 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1170 delete_from_our_metadata_(our_current_position--);
1172 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1175 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1176 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1177 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1178 delete_from_our_metadata_(our_current_position--);
1180 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1183 printf("SV[A]P\tnext\n");
1184 if(!FLAC__metadata_simple_iterator_next(iterator))
1185 return die_("iterator ended early\n");
1186 our_current_position++;
1188 printf("SVA[P]\tinsert PADDING after\n");
1189 padding->length = 5;
1190 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1191 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1192 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1195 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1198 printf("SVAP[P]\tprev\n");
1199 if(!FLAC__metadata_simple_iterator_prev(iterator))
1200 return die_("iterator ended early\n");
1201 our_current_position--;
1203 printf("SVA[P]P\tprev\n");
1204 if(!FLAC__metadata_simple_iterator_prev(iterator))
1205 return die_("iterator ended early\n");
1206 our_current_position--;
1208 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1209 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1210 return die_("setting APPLICATION data");
1211 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1212 return die_("copying object");
1213 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1214 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1216 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1219 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1220 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1221 return die_("setting APPLICATION data");
1222 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1223 return die_("copying object");
1224 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1225 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1227 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1230 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1231 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1232 return die_("setting APPLICATION data");
1233 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1234 return die_("copying object");
1235 our_metadata_.blocks[our_current_position+1]->length = 0;
1236 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1237 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1239 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1242 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1243 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1244 return die_("setting APPLICATION data");
1245 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1246 return die_("copying object");
1247 delete_from_our_metadata_(our_current_position+1);
1248 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1249 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1251 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1254 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1255 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1256 return die_("setting APPLICATION data");
1257 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1258 return die_("copying object");
1259 delete_from_our_metadata_(our_current_position+1);
1260 our_metadata_.blocks[our_current_position]->is_last = true;
1261 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1262 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1264 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1267 printf("SV[A]\tset PADDING (equal size)\n");
1268 padding->length = app->length;
1269 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1270 return die_("copying object");
1271 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1272 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1274 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1277 printf("SV[P]\tinsert PADDING after\n");
1278 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1279 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1280 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1283 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1286 printf("SVP[P]\tinsert PADDING after\n");
1287 padding->length = 5;
1288 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1289 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1290 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1293 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1296 printf("SVPP[P]\tprev\n");
1297 if(!FLAC__metadata_simple_iterator_prev(iterator))
1298 return die_("iterator ended early\n");
1299 our_current_position--;
1301 printf("SVP[P]P\tprev\n");
1302 if(!FLAC__metadata_simple_iterator_prev(iterator))
1303 return die_("iterator ended early\n");
1304 our_current_position--;
1306 printf("SV[P]PP\tprev\n");
1307 if(!FLAC__metadata_simple_iterator_prev(iterator))
1308 return die_("iterator ended early\n");
1309 our_current_position--;
1311 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1312 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1313 return die_("setting APPLICATION data");
1314 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1315 return die_("copying object");
1316 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1317 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1319 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1322 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1323 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1324 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1325 delete_from_our_metadata_(our_current_position--);
1327 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1330 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1331 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1332 return die_("setting APPLICATION data");
1333 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1334 return die_("copying object");
1335 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1336 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1338 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1341 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1342 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1343 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1344 delete_from_our_metadata_(our_current_position--);
1346 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1349 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1350 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1351 return die_("setting APPLICATION data");
1352 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1353 return die_("copying object");
1354 delete_from_our_metadata_(our_current_position+1);
1355 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1356 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1358 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1361 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1362 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1363 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1364 delete_from_our_metadata_(our_current_position--);
1366 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1369 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1370 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1371 return die_("setting APPLICATION data");
1372 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1373 return die_("copying object");
1374 our_metadata_.blocks[our_current_position+1]->length = 0;
1375 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1376 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1378 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1381 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1382 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1383 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1384 delete_from_our_metadata_(our_current_position--);
1386 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1389 printf("S[V]PP\tnext\n");
1390 if(!FLAC__metadata_simple_iterator_next(iterator))
1391 return die_("iterator ended early\n");
1392 our_current_position++;
1394 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1395 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1396 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1397 delete_from_our_metadata_(our_current_position--);
1399 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1402 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1403 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1404 return die_("setting APPLICATION data");
1405 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1406 return die_("copying object");
1407 delete_from_our_metadata_(our_current_position+1);
1408 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1409 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1411 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1414 printf("delete simple iterator\n");
1416 FLAC__metadata_simple_iterator_delete(iterator);
1418 FLAC__metadata_object_delete(app);
1419 FLAC__metadata_object_delete(padding);
1421 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1427 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1429 FLAC__Metadata_Iterator *iterator;
1430 FLAC__Metadata_Chain *chain;
1431 FLAC__StreamMetadata *block, *app, *padding;
1432 FLAC__byte data[2000];
1433 unsigned our_current_position;
1435 /* initialize 'data' to avoid Valgrind errors */
1436 memset(data, 0, sizeof(data));
1438 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1440 printf("generate read-only file\n");
1442 if(!generate_file_(/*include_extras=*/false, is_ogg))
1445 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1448 printf("create chain\n");
1450 if(0 == (chain = FLAC__metadata_chain_new()))
1451 return die_("allocating chain");
1453 printf("read chain\n");
1455 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1456 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1458 printf("[S]VP\ttest initial metadata\n");
1460 if(!compare_chain_(chain, 0, 0))
1462 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1468 printf("switch file to read-write\n");
1470 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1473 printf("create iterator\n");
1474 if(0 == (iterator = FLAC__metadata_iterator_new()))
1475 return die_("allocating memory for iterator");
1477 our_current_position = 0;
1479 FLAC__metadata_iterator_init(iterator, chain);
1481 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1482 return die_("getting block from iterator");
1484 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1486 printf("[S]VP\tmodify STREAMINFO, write\n");
1488 block->data.stream_info.sample_rate = 32000;
1489 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1490 return die_("copying object");
1492 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1493 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1494 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1496 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1499 printf("[S]VP\tnext\n");
1500 if(!FLAC__metadata_iterator_next(iterator))
1501 return die_("iterator ended early\n");
1502 our_current_position++;
1504 printf("S[V]P\tnext\n");
1505 if(!FLAC__metadata_iterator_next(iterator))
1506 return die_("iterator ended early\n");
1507 our_current_position++;
1509 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1510 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1511 return die_("getting block from iterator");
1512 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1513 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1514 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1515 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1516 return die_("setting APPLICATION data");
1517 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1518 return die_("copying object");
1519 if(!FLAC__metadata_iterator_set_block(iterator, app))
1520 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1522 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1523 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1524 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1526 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1529 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1530 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1531 return die_("copying object");
1532 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1533 return die_("setting APPLICATION data");
1534 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1535 return die_("copying object");
1536 if(!FLAC__metadata_iterator_set_block(iterator, app))
1537 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1539 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1540 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1541 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1543 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1546 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1547 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1548 return die_("copying object");
1549 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1550 return die_("setting APPLICATION data");
1551 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1552 return die_("copying object");
1553 if(!FLAC__metadata_iterator_set_block(iterator, app))
1554 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1556 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1557 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1558 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1560 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1563 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1564 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1565 return die_("copying object");
1566 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1567 return die_("setting APPLICATION data");
1568 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1569 return die_("copying object");
1570 if(!FLAC__metadata_iterator_set_block(iterator, app))
1571 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1573 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1574 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1575 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1577 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1580 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1581 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1582 return die_("copying object");
1583 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1584 return die_("setting APPLICATION data");
1585 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1586 return die_("copying object");
1587 if(!FLAC__metadata_iterator_set_block(iterator, app))
1588 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1590 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1591 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1592 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1594 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1597 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1598 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1599 return die_("creating PADDING block");
1600 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1601 return die_("copying object");
1602 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1603 return die_("setting APPLICATION data");
1604 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1605 return die_("copying object");
1606 padding->length = 0;
1607 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1608 return die_("internal error");
1609 if(!FLAC__metadata_iterator_set_block(iterator, app))
1610 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1612 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1613 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1614 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1616 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1619 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1620 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1621 return die_("copying object");
1622 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1623 return die_("setting APPLICATION data");
1624 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1625 return die_("copying object");
1626 our_metadata_.blocks[our_current_position+1]->length = 13;
1627 if(!FLAC__metadata_iterator_set_block(iterator, app))
1628 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1630 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1631 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1632 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1634 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1637 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1638 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1639 return die_("copying object");
1640 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1641 return die_("setting APPLICATION data");
1642 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1643 return die_("copying object");
1644 if(!FLAC__metadata_iterator_set_block(iterator, app))
1645 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1647 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1648 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1649 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1651 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1654 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1655 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1656 return die_("copying object");
1657 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1658 return die_("setting APPLICATION data");
1659 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1660 return die_("copying object");
1661 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1662 if(!FLAC__metadata_iterator_set_block(iterator, app))
1663 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1665 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1666 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1667 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1669 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1672 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1673 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1674 return die_("copying object");
1675 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1676 return die_("setting APPLICATION data");
1677 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1678 return die_("copying object");
1679 delete_from_our_metadata_(our_current_position+1);
1680 if(!FLAC__metadata_iterator_set_block(iterator, app))
1681 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1683 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1684 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1685 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1687 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1690 printf("SV[A]\tprev\n");
1691 if(!FLAC__metadata_iterator_prev(iterator))
1692 return die_("iterator ended early\n");
1693 our_current_position--;
1695 printf("S[V]A\tprev\n");
1696 if(!FLAC__metadata_iterator_prev(iterator))
1697 return die_("iterator ended early\n");
1698 our_current_position--;
1700 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1701 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1702 return die_("creating PADDING block");
1703 padding->length = 30;
1704 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1705 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1707 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1709 printf("[S]VP\tnext\n");
1710 if(!FLAC__metadata_iterator_next(iterator))
1711 return die_("iterator ended early\n");
1712 our_current_position++;
1714 printf("S[V]A\tinsert PADDING after\n");
1715 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1716 return die_("copying metadata");
1717 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1718 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1720 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1723 printf("SV[P]A\tinsert PADDING before\n");
1724 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1725 return die_("creating PADDING block");
1726 padding->length = 17;
1727 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1728 return die_("copying metadata");
1729 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1730 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1732 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1735 printf("SV[P]PA\tinsert PADDING before\n");
1736 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1737 return die_("creating PADDING block");
1738 padding->length = 0;
1739 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1740 return die_("copying metadata");
1741 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1742 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1744 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1747 printf("SV[P]PPA\tnext\n");
1748 if(!FLAC__metadata_iterator_next(iterator))
1749 return die_("iterator ended early\n");
1750 our_current_position++;
1752 printf("SVP[P]PA\tnext\n");
1753 if(!FLAC__metadata_iterator_next(iterator))
1754 return die_("iterator ended early\n");
1755 our_current_position++;
1757 printf("SVPP[P]A\tnext\n");
1758 if(!FLAC__metadata_iterator_next(iterator))
1759 return die_("iterator ended early\n");
1760 our_current_position++;
1762 printf("SVPPP[A]\tinsert PADDING after\n");
1763 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1764 return die_("creating PADDING block");
1765 padding->length = 57;
1766 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1767 return die_("copying metadata");
1768 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1769 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1771 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1774 printf("SVPPPA[P]\tinsert PADDING before\n");
1775 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1776 return die_("creating PADDING block");
1777 padding->length = 99;
1778 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1779 return die_("copying metadata");
1780 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1781 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1783 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1786 printf("delete iterator\n");
1787 FLAC__metadata_iterator_delete(iterator);
1788 our_current_position = 0;
1790 printf("SVPPPAPP\tmerge padding\n");
1791 FLAC__metadata_chain_merge_padding(chain);
1792 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1793 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1794 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1795 delete_from_our_metadata_(7);
1796 delete_from_our_metadata_(4);
1797 delete_from_our_metadata_(3);
1799 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1800 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1801 if(!compare_chain_(chain, 0, 0))
1803 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1806 printf("SVPAP\tsort padding\n");
1807 FLAC__metadata_chain_sort_padding(chain);
1808 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1809 delete_from_our_metadata_(2);
1811 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1812 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1813 if(!compare_chain_(chain, 0, 0))
1815 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1818 printf("create iterator\n");
1819 if(0 == (iterator = FLAC__metadata_iterator_new()))
1820 return die_("allocating memory for iterator");
1822 our_current_position = 0;
1824 FLAC__metadata_iterator_init(iterator, chain);
1826 printf("[S]VAP\tnext\n");
1827 if(!FLAC__metadata_iterator_next(iterator))
1828 return die_("iterator ended early\n");
1829 our_current_position++;
1831 printf("S[V]AP\tnext\n");
1832 if(!FLAC__metadata_iterator_next(iterator))
1833 return die_("iterator ended early\n");
1834 our_current_position++;
1836 printf("SV[A]P\tdelete middle block, replace with padding\n");
1837 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1838 return die_("creating PADDING block");
1839 padding->length = 71;
1840 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1841 return die_("copying object");
1842 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1843 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1845 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1848 printf("S[V]PP\tnext\n");
1849 if(!FLAC__metadata_iterator_next(iterator))
1850 return die_("iterator ended early\n");
1851 our_current_position++;
1853 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1854 delete_from_our_metadata_(our_current_position--);
1855 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1856 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1858 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1861 printf("S[V]P\tnext\n");
1862 if(!FLAC__metadata_iterator_next(iterator))
1863 return die_("iterator ended early\n");
1864 our_current_position++;
1866 printf("SV[P]\tdelete last block, replace with padding\n");
1867 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1868 return die_("creating PADDING block");
1869 padding->length = 219;
1870 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1871 return die_("copying object");
1872 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1873 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1875 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1878 printf("S[V]P\tnext\n");
1879 if(!FLAC__metadata_iterator_next(iterator))
1880 return die_("iterator ended early\n");
1881 our_current_position++;
1883 printf("SV[P]\tdelete last block, don't replace with padding\n");
1884 delete_from_our_metadata_(our_current_position--);
1885 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1886 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1888 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1891 printf("S[V]\tprev\n");
1892 if(!FLAC__metadata_iterator_prev(iterator))
1893 return die_("iterator ended early\n");
1894 our_current_position--;
1896 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1897 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1898 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1900 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1903 printf("delete iterator\n");
1904 FLAC__metadata_iterator_delete(iterator);
1905 our_current_position = 0;
1907 printf("SV\tmerge padding\n");
1908 FLAC__metadata_chain_merge_padding(chain);
1910 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1911 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1912 if(!compare_chain_(chain, 0, 0))
1914 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1917 printf("SV\tsort padding\n");
1918 FLAC__metadata_chain_sort_padding(chain);
1920 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1921 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1922 if(!compare_chain_(chain, 0, 0))
1924 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1928 printf("delete chain\n");
1930 FLAC__metadata_chain_delete(chain);
1932 if(!remove_file_(flacfilename(is_ogg)))
1938 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1940 FLAC__Metadata_Iterator *iterator;
1941 FLAC__Metadata_Chain *chain;
1942 FLAC__IOCallbacks callbacks;
1944 memset(&callbacks, 0, sizeof(callbacks));
1945 callbacks.read = (FLAC__IOCallback_Read)fread;
1946 #ifdef FLAC__VALGRIND_TESTING
1947 callbacks.write = chain_write_cb_;
1949 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1951 callbacks.seek = chain_seek_cb_;
1952 callbacks.tell = chain_tell_cb_;
1953 callbacks.eof = chain_eof_cb_;
1955 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1957 printf("generate file\n");
1959 if(!generate_file_(/*include_extras=*/false, is_ogg))
1962 printf("create chain\n");
1964 if(0 == (chain = FLAC__metadata_chain_new()))
1965 return die_("allocating chain");
1967 printf("read chain (filename-based)\n");
1969 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1970 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1972 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1974 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1975 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1976 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1977 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1978 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1981 printf("read chain (filename-based)\n");
1983 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1984 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1986 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1988 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1989 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1990 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1991 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1992 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1995 printf("read chain (callback-based)\n");
1997 FILE *file = fopen(flacfilename(is_ogg), "rb");
1999 return die_("opening file");
2000 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2002 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2007 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2009 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2010 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2011 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2012 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2013 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2016 printf("read chain (callback-based)\n");
2018 FILE *file = fopen(flacfilename(is_ogg), "rb");
2020 return die_("opening file");
2021 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2023 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2028 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2030 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2031 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2033 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2035 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2037 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2038 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2039 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2040 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2041 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2044 printf("read chain (callback-based)\n");
2046 FILE *file = fopen(flacfilename(is_ogg), "rb");
2048 return die_("opening file");
2049 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2051 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2056 printf("create iterator\n");
2057 if(0 == (iterator = FLAC__metadata_iterator_new()))
2058 return die_("allocating memory for iterator");
2060 FLAC__metadata_iterator_init(iterator, chain);
2062 printf("[S]VP\tnext\n");
2063 if(!FLAC__metadata_iterator_next(iterator))
2064 return die_("iterator ended early\n");
2066 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2067 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2068 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2070 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2072 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2073 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2075 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2077 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2079 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2080 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2081 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2082 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2083 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2086 printf("delete iterator\n");
2088 FLAC__metadata_iterator_delete(iterator);
2090 printf("delete chain\n");
2092 FLAC__metadata_chain_delete(chain);
2094 if(!remove_file_(flacfilename(is_ogg)))
2100 FLAC__bool test_metadata_file_manipulation(void)
2102 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2104 our_metadata_.num_blocks = 0;
2106 if(!test_level_0_())
2109 if(!test_level_1_())
2112 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2114 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2116 if(!test_level_2_misc_(/*is_ogg=*/false))
2119 if(FLAC_API_SUPPORTS_OGG_FLAC) {
2120 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2122 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2125 /* when ogg flac write is supported, will have to add this: */
2126 if(!test_level_2_misc_(/*is_ogg=*/true))