1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 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() */
30 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
31 #include <utime.h> /* for utime() */
32 #include <unistd.h> /* for chown(), unlink() */
34 #include <sys/stat.h> /* for stat(), maybe chmod() */
35 #include "FLAC/assert.h"
36 #include "FLAC/stream_decoder.h"
37 #include "FLAC/metadata.h"
38 #include "share/grabbag.h"
39 #include "share/compat.h"
40 #include "test_libs_common/file_utils_flac.h"
41 #include "test_libs_common/metadata_utils.h"
45 /******************************************************************************
46 The general strategy of these tests (for interface levels 1 and 2) is
47 to create a dummy FLAC file with a known set of initial metadata
48 blocks, then keep a mirror locally of what we expect the metadata to be
49 after each operation. Then testing becomes a simple matter of running
50 a FLAC__StreamDecoder over the dummy file after each operation, comparing
51 the decoded metadata to what's in our local copy. If there are any
52 differences in the metadata, or the actual audio data is corrupted, we
53 will catch it while decoding.
54 ******************************************************************************/
57 FLAC__bool error_occurred;
58 } decoder_client_struct;
61 FLAC__StreamMetadata *blocks[64];
63 } our_metadata_struct;
65 /* our copy of the metadata in flacfilename() */
66 static our_metadata_struct our_metadata_;
68 /* the current block number that corresponds to the position of the iterator we are testing */
69 static unsigned mc_our_block_number_ = 0;
71 static const char *flacfilename(FLAC__bool is_ogg)
73 return is_ogg? "metadata.oga" : "metadata.flac";
76 static FLAC__bool die_(const char *msg)
78 printf("ERROR: %s\n", msg);
82 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
84 printf("ERROR: %s\n", msg);
85 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
89 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
91 printf("ERROR: %s\n", msg);
92 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
96 static void *malloc_or_die_(size_t size)
98 void *x = malloc(size);
100 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
106 static char *strdup_or_die_(const char *s)
110 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
116 /* functions for working with our metadata copy */
118 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
121 FLAC__StreamMetadata *obj = block;
122 FLAC__ASSERT(position < our_metadata_.num_blocks);
124 if(0 == (obj = FLAC__metadata_object_clone(block)))
125 return die_("during FLAC__metadata_object_clone()");
127 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
128 our_metadata_.blocks[position] = obj;
130 /* set the is_last flags */
131 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
132 our_metadata_.blocks[i]->is_last = false;
133 our_metadata_.blocks[i]->is_last = true;
138 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
141 FLAC__StreamMetadata *obj = block;
143 if(0 == (obj = FLAC__metadata_object_clone(block)))
144 return die_("during FLAC__metadata_object_clone()");
146 if(position > our_metadata_.num_blocks) {
147 position = our_metadata_.num_blocks;
150 for(i = our_metadata_.num_blocks; i > position; i--)
151 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
153 our_metadata_.blocks[position] = obj;
154 our_metadata_.num_blocks++;
156 /* set the is_last flags */
157 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
158 our_metadata_.blocks[i]->is_last = false;
159 our_metadata_.blocks[i]->is_last = true;
164 static void delete_from_our_metadata_(unsigned position)
167 FLAC__ASSERT(position < our_metadata_.num_blocks);
168 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
169 for(i = position; i < our_metadata_.num_blocks - 1; i++)
170 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
171 our_metadata_.num_blocks--;
173 /* set the is_last flags */
174 if(our_metadata_.num_blocks > 0) {
175 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
176 our_metadata_.blocks[i]->is_last = false;
177 our_metadata_.blocks[i]->is_last = true;
182 * This wad of functions supports filename- and callback-based chain reading/writing.
183 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
185 static FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
187 static const char *tempfile_suffix = ".metadata_edit";
189 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
191 strcpy(*tempfilename, filename);
192 strcat(*tempfilename, tempfile_suffix);
194 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
200 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
203 (void)fclose(*tempfile);
207 if(0 != *tempfilename) {
208 (void)unlink(*tempfilename);
214 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
216 FLAC__ASSERT(0 != filename);
217 FLAC__ASSERT(0 != tempfile);
218 FLAC__ASSERT(0 != tempfilename);
219 FLAC__ASSERT(0 != *tempfilename);
222 (void)fclose(*tempfile);
226 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
227 /* on some flavors of windows, rename() will fail if the destination already exists */
228 if(unlink(filename) < 0) {
229 cleanup_tempfile_(tempfile, tempfilename);
234 if(0 != rename(*tempfilename, filename)) {
235 cleanup_tempfile_(tempfile, tempfilename);
239 cleanup_tempfile_(tempfile, tempfilename);
244 static FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
246 FLAC__ASSERT(0 != filename);
247 FLAC__ASSERT(0 != stats);
248 return (0 == stat(filename, stats));
251 static void set_file_stats_(const char *filename, struct stat *stats)
253 struct utimbuf srctime;
255 FLAC__ASSERT(0 != filename);
256 FLAC__ASSERT(0 != stats);
258 srctime.actime = stats->st_atime;
259 srctime.modtime = stats->st_mtime;
260 (void)chmod(filename, stats->st_mode);
261 (void)utime(filename, &srctime);
262 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
263 (void)chown(filename, stats->st_uid, -1);
264 (void)chown(filename, -1, stats->st_gid);
268 #ifdef FLAC__VALGRIND_TESTING
269 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
271 FILE *stream = (FILE*)handle;
272 size_t ret = fwrite(ptr, size, nmemb, stream);
279 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
281 off_t o = (off_t)offset;
282 FLAC__ASSERT(offset == o);
283 return fseeko((FILE*)handle, o, whence);
286 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
288 return ftello((FILE*)handle);
291 static int chain_eof_cb_(FLAC__IOHandle handle)
293 return feof((FILE*)handle);
296 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)
299 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
301 FLAC__IOCallbacks callbacks;
303 memset(&callbacks, 0, sizeof(callbacks));
304 callbacks.read = (FLAC__IOCallback_Read)fread;
305 #ifdef FLAC__VALGRIND_TESTING
306 callbacks.write = chain_write_cb_;
308 callbacks.write = (FLAC__IOCallback_Write)fwrite;
310 callbacks.seek = chain_seek_cb_;
311 callbacks.eof = chain_eof_cb_;
313 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
315 FILE *file, *tempfile = 0;
317 if(preserve_file_stats) {
318 if(!get_file_stats_(filename, &stats))
321 if(0 == (file = fopen(filename, "rb")))
322 return false; /*@@@@ chain status still says OK though */
323 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
325 cleanup_tempfile_(&tempfile, &tempfilename);
326 return false; /*@@@@ chain status still says OK though */
328 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
336 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
338 if(preserve_file_stats)
339 set_file_stats_(filename, &stats);
342 FILE *file = fopen(filename, "r+b");
344 return false; /*@@@@ chain status still says OK though */
345 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
354 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based, FLAC__bool is_ogg)
358 FLAC__metadata_chain_read_ogg(chain, flacfilename(is_ogg)) :
359 FLAC__metadata_chain_read(chain, flacfilename(is_ogg))
362 FLAC__IOCallbacks callbacks;
364 memset(&callbacks, 0, sizeof(callbacks));
365 callbacks.read = (FLAC__IOCallback_Read)fread;
366 callbacks.seek = chain_seek_cb_;
367 callbacks.tell = chain_tell_cb_;
371 FILE *file = fopen(filename, "rb");
373 return false; /*@@@@ chain status still says OK though */
375 FLAC__metadata_chain_read_ogg_with_callbacks(chain, (FLAC__IOHandle)file, callbacks) :
376 FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)
384 /* function for comparing our metadata to a FLAC__Metadata_Chain */
386 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
389 FLAC__Metadata_Iterator *iterator;
390 FLAC__StreamMetadata *block;
391 FLAC__bool next_ok = true;
393 FLAC__ASSERT(0 != chain);
395 printf("\tcomparing chain... ");
398 if(0 == (iterator = FLAC__metadata_iterator_new()))
399 return die_("allocating memory for iterator");
401 FLAC__metadata_iterator_init(iterator, chain);
408 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
409 FLAC__metadata_iterator_delete(iterator);
410 return die_("getting block from iterator");
413 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
414 FLAC__metadata_iterator_delete(iterator);
415 return die_("metadata block mismatch");
419 next_ok = FLAC__metadata_iterator_next(iterator);
420 } while(i < our_metadata_.num_blocks && next_ok);
422 FLAC__metadata_iterator_delete(iterator);
425 return die_("chain has more blocks than expected");
427 if(i < our_metadata_.num_blocks)
428 return die_("short block count in chain");
430 if(0 != current_block) {
431 printf("CURRENT_POSITION... ");
434 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
435 return die_("metadata block mismatch");
443 /* decoder callbacks for checking the file */
445 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
447 (void)decoder, (void)buffer, (void)client_data;
450 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
451 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
453 printf("content... ");
457 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
460 /* this version pays no attention to the metadata */
461 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
463 (void)decoder, (void)metadata, (void)client_data;
465 printf("%d... ", mc_our_block_number_);
468 mc_our_block_number_++;
471 /* this version is used when we want to compare to our metadata copy */
472 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
474 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
478 /* don't bother checking if we've already hit an error */
479 if(dcd->error_occurred)
482 printf("%d... ", mc_our_block_number_);
485 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
486 (void)die_("got more metadata blocks than expected");
487 dcd->error_occurred = true;
490 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
491 (void)die_("metadata block mismatch");
492 dcd->error_occurred = true;
495 mc_our_block_number_++;
498 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
500 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
503 dcd->error_occurred = true;
504 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
507 static FLAC__bool generate_file_(FLAC__bool include_extras, FLAC__bool is_ogg)
509 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
510 FLAC__StreamMetadata *metadata[4];
511 unsigned i = 0, n = 0;
513 printf("generating %sFLAC file for test\n", is_ogg? "Ogg " : "");
515 while(our_metadata_.num_blocks > 0)
516 delete_from_our_metadata_(0);
518 streaminfo.is_last = false;
519 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
520 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
521 streaminfo.data.stream_info.min_blocksize = 576;
522 streaminfo.data.stream_info.max_blocksize = 576;
523 streaminfo.data.stream_info.min_framesize = 0;
524 streaminfo.data.stream_info.max_framesize = 0;
525 streaminfo.data.stream_info.sample_rate = 44100;
526 streaminfo.data.stream_info.channels = 1;
527 streaminfo.data.stream_info.bits_per_sample = 8;
528 streaminfo.data.stream_info.total_samples = 0;
529 memset(streaminfo.data.stream_info.md5sum, 0, 16);
532 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
533 vorbiscomment.is_last = false;
534 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
535 vorbiscomment.length = (4 + vendor_string_length) + 4;
536 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
537 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
538 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
539 vorbiscomment.data.vorbis_comment.num_comments = 0;
540 vorbiscomment.data.vorbis_comment.comments = 0;
544 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
545 return die_("priming our metadata");
546 cuesheet->is_last = false;
547 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
548 cuesheet->data.cue_sheet.lead_in = 123;
549 cuesheet->data.cue_sheet.is_cd = false;
550 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
551 return die_("priming our metadata");
552 cuesheet->data.cue_sheet.tracks[0].number = 1;
553 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
554 return die_("priming our metadata");
558 picture.is_last = false;
559 picture.type = FLAC__METADATA_TYPE_PICTURE;
562 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
563 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
564 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
565 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
566 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
567 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
568 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
569 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
572 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
573 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
574 picture.length += strlen(picture.data.picture.mime_type);
575 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
576 picture.length += strlen((const char *)picture.data.picture.description);
577 picture.data.picture.width = 300;
578 picture.data.picture.height = 300;
579 picture.data.picture.depth = 24;
580 picture.data.picture.colors = 0;
581 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
582 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
583 picture.length += picture.data.picture.data_length;
586 padding.is_last = true;
587 padding.type = FLAC__METADATA_TYPE_PADDING;
588 padding.length = 1234;
590 metadata[n++] = &vorbiscomment;
592 metadata[n++] = cuesheet;
593 metadata[n++] = &picture;
595 metadata[n++] = &padding;
598 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
599 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
600 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
601 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
602 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
604 return die_("priming our metadata");
606 if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), 0, 512 * 1024, &streaminfo, metadata, n))
607 return die_("creating the encoded file");
609 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
610 free(picture.data.picture.mime_type);
611 free(picture.data.picture.description);
612 free(picture.data.picture.data);
614 FLAC__metadata_object_delete(cuesheet);
619 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
621 const char *filename = flacfilename(is_ogg);
622 FLAC__StreamDecoder *decoder;
623 decoder_client_struct decoder_client_data;
625 FLAC__ASSERT(0 != metadata_callback);
627 mc_our_block_number_ = 0;
628 decoder_client_data.error_occurred = false;
630 printf("\ttesting '%s'... ", filename);
633 if(0 == (decoder = FLAC__stream_decoder_new()))
634 return die_("couldn't allocate decoder instance");
636 FLAC__stream_decoder_set_md5_checking(decoder, true);
637 FLAC__stream_decoder_set_metadata_respond_all(decoder);
640 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
641 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
642 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
644 (void)FLAC__stream_decoder_finish(decoder);
645 FLAC__stream_decoder_delete(decoder);
646 return die_("initializing decoder\n");
648 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
649 (void)FLAC__stream_decoder_finish(decoder);
650 FLAC__stream_decoder_delete(decoder);
651 return die_("decoding file\n");
654 (void)FLAC__stream_decoder_finish(decoder);
655 FLAC__stream_decoder_delete(decoder);
657 if(decoder_client_data.error_occurred)
660 if(mc_our_block_number_ != our_metadata_.num_blocks)
661 return die_("short metadata block count");
667 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
669 if(!grabbag__file_change_stats(filename, read_only))
670 return die_("during grabbag__file_change_stats()");
675 static FLAC__bool remove_file_(const char *filename)
677 while(our_metadata_.num_blocks > 0)
678 delete_from_our_metadata_(0);
680 if(!grabbag__file_remove_file(filename))
681 return die_("removing file");
686 static FLAC__bool test_level_0_(void)
688 FLAC__StreamMetadata streaminfo;
689 FLAC__StreamMetadata *tags = 0;
690 FLAC__StreamMetadata *cuesheet = 0;
691 FLAC__StreamMetadata *picture = 0;
693 printf("\n\n++++++ testing level 0 interface\n");
695 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
698 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
701 printf("testing FLAC__metadata_get_streaminfo()... ");
703 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
704 return die_("during FLAC__metadata_get_streaminfo()");
706 /* check to see if some basic data matches (c.f. generate_file_()) */
707 if(streaminfo.data.stream_info.channels != 1)
708 return die_("mismatch in streaminfo.data.stream_info.channels");
709 if(streaminfo.data.stream_info.bits_per_sample != 8)
710 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
711 if(streaminfo.data.stream_info.sample_rate != 44100)
712 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
713 if(streaminfo.data.stream_info.min_blocksize != 576)
714 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
715 if(streaminfo.data.stream_info.max_blocksize != 576)
716 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
720 printf("testing FLAC__metadata_get_tags()... ");
722 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
723 return die_("during FLAC__metadata_get_tags()");
725 /* check to see if some basic data matches (c.f. generate_file_()) */
726 if(tags->data.vorbis_comment.num_comments != 0)
727 return die_("mismatch in tags->data.vorbis_comment.num_comments");
731 FLAC__metadata_object_delete(tags);
733 printf("testing FLAC__metadata_get_cuesheet()... ");
735 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
736 return die_("during FLAC__metadata_get_cuesheet()");
738 /* check to see if some basic data matches (c.f. generate_file_()) */
739 if(cuesheet->data.cue_sheet.lead_in != 123)
740 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
744 FLAC__metadata_object_delete(cuesheet);
746 printf("testing FLAC__metadata_get_picture()... ");
748 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)))
749 return die_("during FLAC__metadata_get_picture()");
751 /* check to see if some basic data matches (c.f. generate_file_()) */
752 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
753 return die_("mismatch in picture->data.picture.type");
757 FLAC__metadata_object_delete(picture);
759 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
765 static FLAC__bool test_level_1_(void)
767 FLAC__Metadata_SimpleIterator *iterator;
768 FLAC__StreamMetadata *block, *app, *padding;
769 FLAC__byte data[1000];
770 unsigned our_current_position = 0;
772 /* initialize 'data' to avoid Valgrind errors */
773 memset(data, 0, sizeof(data));
775 printf("\n\n++++++ testing level 1 interface\n");
777 /************************************************************/
779 printf("simple iterator on read-only file\n");
781 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
784 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
787 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
790 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
791 return die_("FLAC__metadata_simple_iterator_new()");
793 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
794 return die_("FLAC__metadata_simple_iterator_init() returned false");
796 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
797 if(FLAC__metadata_simple_iterator_is_writable(iterator))
798 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
800 printf("iterate forwards\n");
802 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
803 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
804 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
805 return die_("getting block 0");
806 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
807 return die_("expected STREAMINFO type");
809 return die_("expected is_last to be false");
810 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
811 return die_("bad STREAMINFO length");
812 /* check to see if some basic data matches (c.f. generate_file_()) */
813 if(block->data.stream_info.channels != 1)
814 return die_("mismatch in channels");
815 if(block->data.stream_info.bits_per_sample != 8)
816 return die_("mismatch in bits_per_sample");
817 if(block->data.stream_info.sample_rate != 44100)
818 return die_("mismatch in sample_rate");
819 if(block->data.stream_info.min_blocksize != 576)
820 return die_("mismatch in min_blocksize");
821 if(block->data.stream_info.max_blocksize != 576)
822 return die_("mismatch in max_blocksize");
823 FLAC__metadata_object_delete(block);
825 if(!FLAC__metadata_simple_iterator_next(iterator))
826 return die_("forward iterator ended early");
827 our_current_position++;
829 if(!FLAC__metadata_simple_iterator_next(iterator))
830 return die_("forward iterator ended early");
831 our_current_position++;
833 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
834 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
835 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
836 return die_("getting block 2");
837 if(block->type != FLAC__METADATA_TYPE_PADDING)
838 return die_("expected PADDING type");
840 return die_("expected is_last to be true");
841 /* check to see if some basic data matches (c.f. generate_file_()) */
842 if(block->length != 1234)
843 return die_("bad PADDING length");
844 FLAC__metadata_object_delete(block);
846 if(FLAC__metadata_simple_iterator_next(iterator))
847 return die_("forward iterator returned true but should have returned false");
849 printf("iterate backwards\n");
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 ended early");
854 if(FLAC__metadata_simple_iterator_prev(iterator))
855 return die_("reverse iterator returned true but should have returned false");
857 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
859 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
860 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
862 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
864 FLAC__metadata_simple_iterator_delete(iterator);
866 /************************************************************/
868 printf("simple iterator on writable file\n");
870 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
873 printf("creating APPLICATION block\n");
875 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
876 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
877 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
879 printf("creating PADDING block\n");
881 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
882 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
883 padding->length = 20;
885 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
886 return die_("FLAC__metadata_simple_iterator_new()");
888 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
889 return die_("FLAC__metadata_simple_iterator_init() returned false");
890 our_current_position = 0;
892 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
894 printf("[S]VP\ttry to write over STREAMINFO block...\n");
895 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
896 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
898 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
900 printf("[S]VP\tnext\n");
901 if(!FLAC__metadata_simple_iterator_next(iterator))
902 return die_("iterator ended early\n");
903 our_current_position++;
905 printf("S[V]P\tnext\n");
906 if(!FLAC__metadata_simple_iterator_next(iterator))
907 return die_("iterator ended early\n");
908 our_current_position++;
910 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
911 padding->length = 25;
912 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
913 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
914 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
917 printf("SVP[P]\tprev\n");
918 if(!FLAC__metadata_simple_iterator_prev(iterator))
919 return die_("iterator ended early\n");
920 our_current_position--;
922 printf("SV[P]P\tprev\n");
923 if(!FLAC__metadata_simple_iterator_prev(iterator))
924 return die_("iterator ended early\n");
925 our_current_position--;
927 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
928 padding->length = 30;
929 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
930 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
931 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
934 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
937 printf("SV[P]PP\tprev\n");
938 if(!FLAC__metadata_simple_iterator_prev(iterator))
939 return die_("iterator ended early\n");
940 our_current_position--;
942 printf("S[V]PPP\tprev\n");
943 if(!FLAC__metadata_simple_iterator_prev(iterator))
944 return die_("iterator ended early\n");
945 our_current_position--;
947 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
948 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
949 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
951 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
954 printf("[S]VPPP\tnext\n");
955 if(!FLAC__metadata_simple_iterator_next(iterator))
956 return die_("iterator ended early\n");
957 our_current_position++;
959 printf("S[V]PPP\tnext\n");
960 if(!FLAC__metadata_simple_iterator_next(iterator))
961 return die_("iterator ended early\n");
962 our_current_position++;
964 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
965 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
966 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
967 our_current_position--;
969 printf("S[V]PPP\tnext\n");
970 if(!FLAC__metadata_simple_iterator_next(iterator))
971 return die_("iterator ended early\n");
972 our_current_position++;
974 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
975 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
976 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
977 delete_from_our_metadata_(our_current_position--);
979 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
982 printf("S[V]PP\tnext\n");
983 if(!FLAC__metadata_simple_iterator_next(iterator))
984 return die_("iterator ended early\n");
985 our_current_position++;
987 printf("SV[P]P\tnext\n");
988 if(!FLAC__metadata_simple_iterator_next(iterator))
989 return die_("iterator ended early\n");
990 our_current_position++;
992 printf("SVP[P]\tdelete (last block), replace with padding\n");
993 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
994 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
995 our_current_position--;
997 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1000 printf("SV[P]P\tnext\n");
1001 if(!FLAC__metadata_simple_iterator_next(iterator))
1002 return die_("iterator ended early\n");
1003 our_current_position++;
1005 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1006 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1007 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1008 delete_from_our_metadata_(our_current_position--);
1010 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1013 printf("SV[P]\tprev\n");
1014 if(!FLAC__metadata_simple_iterator_prev(iterator))
1015 return die_("iterator ended early\n");
1016 our_current_position--;
1018 printf("S[V]P\tprev\n");
1019 if(!FLAC__metadata_simple_iterator_prev(iterator))
1020 return die_("iterator ended early\n");
1021 our_current_position--;
1023 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1024 FLAC__ASSERT(our_current_position == 0);
1025 block = FLAC__metadata_simple_iterator_get_block(iterator);
1026 block->data.stream_info.sample_rate = 32000;
1027 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1028 return die_("copying object");
1029 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1030 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1031 FLAC__metadata_object_delete(block);
1033 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1036 printf("[S]VP\tnext\n");
1037 if(!FLAC__metadata_simple_iterator_next(iterator))
1038 return die_("iterator ended early\n");
1039 our_current_position++;
1041 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1042 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1043 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1044 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1045 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1047 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1049 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1052 printf("SV[A]P\tnext\n");
1053 if(!FLAC__metadata_simple_iterator_next(iterator))
1054 return die_("iterator ended early\n");
1055 our_current_position++;
1057 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1058 app->data.application.id[0] = 'f'; /* twiddle the id */
1059 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1060 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1061 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1063 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1065 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1068 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1069 app->data.application.id[0] = 'g'; /* twiddle the id */
1070 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1071 return die_("setting APPLICATION data");
1072 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1073 return die_("copying object");
1074 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1075 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1077 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1080 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1081 app->data.application.id[0] = 'h'; /* twiddle the id */
1082 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1083 return die_("setting APPLICATION data");
1084 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1085 return die_("copying object");
1086 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1087 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1089 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1092 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1093 app->data.application.id[0] = 'i'; /* twiddle the id */
1094 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1095 return die_("setting APPLICATION data");
1096 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1097 return die_("copying object");
1098 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1099 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1100 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1102 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1105 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1106 app->data.application.id[0] = 'j'; /* twiddle the id */
1107 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1108 return die_("setting APPLICATION data");
1109 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1110 return die_("copying object");
1111 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1112 return die_("copying object");
1113 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1114 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1115 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1117 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1120 printf("SVA[A]PP\tnext\n");
1121 if(!FLAC__metadata_simple_iterator_next(iterator))
1122 return die_("iterator ended early\n");
1123 our_current_position++;
1125 printf("SVAA[P]P\tnext\n");
1126 if(!FLAC__metadata_simple_iterator_next(iterator))
1127 return die_("iterator ended early\n");
1128 our_current_position++;
1130 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1131 padding->length = 5;
1132 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1133 return die_("copying object");
1134 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1135 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1137 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1140 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1141 app->data.application.id[0] = 'k'; /* twiddle the id */
1142 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1143 return die_("copying object");
1144 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1145 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1147 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1150 printf("SVAAP[A]\tset PADDING (equal)\n");
1151 padding->length = 27;
1152 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1153 return die_("copying object");
1154 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1155 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1157 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1160 printf("SVAAP[P]\tprev\n");
1161 if(!FLAC__metadata_simple_iterator_prev(iterator))
1162 return die_("iterator ended early\n");
1163 our_current_position--;
1165 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1166 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1167 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1168 delete_from_our_metadata_(our_current_position--);
1170 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1173 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1174 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1175 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1176 delete_from_our_metadata_(our_current_position--);
1178 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1181 printf("SV[A]P\tnext\n");
1182 if(!FLAC__metadata_simple_iterator_next(iterator))
1183 return die_("iterator ended early\n");
1184 our_current_position++;
1186 printf("SVA[P]\tinsert PADDING after\n");
1187 padding->length = 5;
1188 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1189 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1190 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1193 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1196 printf("SVAP[P]\tprev\n");
1197 if(!FLAC__metadata_simple_iterator_prev(iterator))
1198 return die_("iterator ended early\n");
1199 our_current_position--;
1201 printf("SVA[P]P\tprev\n");
1202 if(!FLAC__metadata_simple_iterator_prev(iterator))
1203 return die_("iterator ended early\n");
1204 our_current_position--;
1206 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1207 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1208 return die_("setting APPLICATION data");
1209 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1210 return die_("copying object");
1211 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1212 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1214 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1217 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1218 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1219 return die_("setting APPLICATION data");
1220 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1221 return die_("copying object");
1222 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1223 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1225 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1228 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1229 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1230 return die_("setting APPLICATION data");
1231 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1232 return die_("copying object");
1233 our_metadata_.blocks[our_current_position+1]->length = 0;
1234 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1235 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1237 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1240 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1241 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1242 return die_("setting APPLICATION data");
1243 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1244 return die_("copying object");
1245 delete_from_our_metadata_(our_current_position+1);
1246 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1247 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1249 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1252 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1253 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1254 return die_("setting APPLICATION data");
1255 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1256 return die_("copying object");
1257 delete_from_our_metadata_(our_current_position+1);
1258 our_metadata_.blocks[our_current_position]->is_last = true;
1259 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1260 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1262 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1265 printf("SV[A]\tset PADDING (equal size)\n");
1266 padding->length = app->length;
1267 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1268 return die_("copying object");
1269 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1270 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1272 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1275 printf("SV[P]\tinsert PADDING after\n");
1276 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1277 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1278 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1281 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1284 printf("SVP[P]\tinsert PADDING after\n");
1285 padding->length = 5;
1286 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1287 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1288 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1291 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1294 printf("SVPP[P]\tprev\n");
1295 if(!FLAC__metadata_simple_iterator_prev(iterator))
1296 return die_("iterator ended early\n");
1297 our_current_position--;
1299 printf("SVP[P]P\tprev\n");
1300 if(!FLAC__metadata_simple_iterator_prev(iterator))
1301 return die_("iterator ended early\n");
1302 our_current_position--;
1304 printf("SV[P]PP\tprev\n");
1305 if(!FLAC__metadata_simple_iterator_prev(iterator))
1306 return die_("iterator ended early\n");
1307 our_current_position--;
1309 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1310 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1311 return die_("setting APPLICATION data");
1312 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1313 return die_("copying object");
1314 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1315 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1317 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1320 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1321 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1322 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1323 delete_from_our_metadata_(our_current_position--);
1325 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1328 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1329 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1330 return die_("setting APPLICATION data");
1331 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1332 return die_("copying object");
1333 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1334 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1336 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1339 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1340 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1341 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1342 delete_from_our_metadata_(our_current_position--);
1344 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1347 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1348 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1349 return die_("setting APPLICATION data");
1350 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1351 return die_("copying object");
1352 delete_from_our_metadata_(our_current_position+1);
1353 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1354 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1356 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1359 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1360 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1361 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1362 delete_from_our_metadata_(our_current_position--);
1364 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1367 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1368 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1369 return die_("setting APPLICATION data");
1370 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1371 return die_("copying object");
1372 our_metadata_.blocks[our_current_position+1]->length = 0;
1373 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1374 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1376 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1379 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1380 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1381 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1382 delete_from_our_metadata_(our_current_position--);
1384 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1387 printf("S[V]PP\tnext\n");
1388 if(!FLAC__metadata_simple_iterator_next(iterator))
1389 return die_("iterator ended early\n");
1390 our_current_position++;
1392 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1393 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1394 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1395 delete_from_our_metadata_(our_current_position--);
1397 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1400 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1401 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1402 return die_("setting APPLICATION data");
1403 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1404 return die_("copying object");
1405 delete_from_our_metadata_(our_current_position+1);
1406 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1407 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1409 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1412 printf("delete simple iterator\n");
1414 FLAC__metadata_simple_iterator_delete(iterator);
1416 FLAC__metadata_object_delete(app);
1417 FLAC__metadata_object_delete(padding);
1419 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1425 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1427 FLAC__Metadata_Iterator *iterator;
1428 FLAC__Metadata_Chain *chain;
1429 FLAC__StreamMetadata *block, *app, *padding;
1430 FLAC__byte data[2000];
1431 unsigned our_current_position;
1433 /* initialize 'data' to avoid Valgrind errors */
1434 memset(data, 0, sizeof(data));
1436 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1438 printf("generate read-only file\n");
1440 if(!generate_file_(/*include_extras=*/false, is_ogg))
1443 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1446 printf("create chain\n");
1448 if(0 == (chain = FLAC__metadata_chain_new()))
1449 return die_("allocating chain");
1451 printf("read chain\n");
1453 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1454 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1456 printf("[S]VP\ttest initial metadata\n");
1458 if(!compare_chain_(chain, 0, 0))
1460 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1466 printf("switch file to read-write\n");
1468 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1471 printf("create iterator\n");
1472 if(0 == (iterator = FLAC__metadata_iterator_new()))
1473 return die_("allocating memory for iterator");
1475 our_current_position = 0;
1477 FLAC__metadata_iterator_init(iterator, chain);
1479 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1480 return die_("getting block from iterator");
1482 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1484 printf("[S]VP\tmodify STREAMINFO, write\n");
1486 block->data.stream_info.sample_rate = 32000;
1487 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1488 return die_("copying object");
1490 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1491 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1492 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1494 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1497 printf("[S]VP\tnext\n");
1498 if(!FLAC__metadata_iterator_next(iterator))
1499 return die_("iterator ended early\n");
1500 our_current_position++;
1502 printf("S[V]P\tnext\n");
1503 if(!FLAC__metadata_iterator_next(iterator))
1504 return die_("iterator ended early\n");
1505 our_current_position++;
1507 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1508 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1509 return die_("getting block from iterator");
1510 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1511 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1512 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1513 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1514 return die_("setting APPLICATION data");
1515 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1516 return die_("copying object");
1517 if(!FLAC__metadata_iterator_set_block(iterator, app))
1518 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1520 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1521 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1522 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1524 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1527 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1528 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1529 return die_("copying object");
1530 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1531 return die_("setting APPLICATION data");
1532 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1533 return die_("copying object");
1534 if(!FLAC__metadata_iterator_set_block(iterator, app))
1535 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1537 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1538 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1539 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1541 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1544 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1545 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1546 return die_("copying object");
1547 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1548 return die_("setting APPLICATION data");
1549 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1550 return die_("copying object");
1551 if(!FLAC__metadata_iterator_set_block(iterator, app))
1552 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1554 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1555 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1556 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1558 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1561 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1562 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1563 return die_("copying object");
1564 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1565 return die_("setting APPLICATION data");
1566 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1567 return die_("copying object");
1568 if(!FLAC__metadata_iterator_set_block(iterator, app))
1569 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1571 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1572 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1573 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1575 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1578 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1579 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1580 return die_("copying object");
1581 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1582 return die_("setting APPLICATION data");
1583 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1584 return die_("copying object");
1585 if(!FLAC__metadata_iterator_set_block(iterator, app))
1586 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1588 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1589 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1590 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1592 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1595 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1596 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1597 return die_("creating PADDING block");
1598 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1599 return die_("copying object");
1600 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1601 return die_("setting APPLICATION data");
1602 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1603 return die_("copying object");
1604 padding->length = 0;
1605 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1606 return die_("internal error");
1607 if(!FLAC__metadata_iterator_set_block(iterator, app))
1608 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1610 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1611 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1612 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1614 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1617 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1618 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1619 return die_("copying object");
1620 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1621 return die_("setting APPLICATION data");
1622 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1623 return die_("copying object");
1624 our_metadata_.blocks[our_current_position+1]->length = 13;
1625 if(!FLAC__metadata_iterator_set_block(iterator, app))
1626 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1628 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1629 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1630 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1632 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1635 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1636 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1637 return die_("copying object");
1638 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1639 return die_("setting APPLICATION data");
1640 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1641 return die_("copying object");
1642 if(!FLAC__metadata_iterator_set_block(iterator, app))
1643 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1645 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1646 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1647 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1649 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1652 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1653 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1654 return die_("copying object");
1655 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1656 return die_("setting APPLICATION data");
1657 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1658 return die_("copying object");
1659 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1660 if(!FLAC__metadata_iterator_set_block(iterator, app))
1661 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1663 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1664 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1665 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1667 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1670 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1671 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1672 return die_("copying object");
1673 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1674 return die_("setting APPLICATION data");
1675 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1676 return die_("copying object");
1677 delete_from_our_metadata_(our_current_position+1);
1678 if(!FLAC__metadata_iterator_set_block(iterator, app))
1679 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1681 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1682 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1683 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1685 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1688 printf("SV[A]\tprev\n");
1689 if(!FLAC__metadata_iterator_prev(iterator))
1690 return die_("iterator ended early\n");
1691 our_current_position--;
1693 printf("S[V]A\tprev\n");
1694 if(!FLAC__metadata_iterator_prev(iterator))
1695 return die_("iterator ended early\n");
1696 our_current_position--;
1698 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1699 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1700 return die_("creating PADDING block");
1701 padding->length = 30;
1702 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1703 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1705 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1707 printf("[S]VP\tnext\n");
1708 if(!FLAC__metadata_iterator_next(iterator))
1709 return die_("iterator ended early\n");
1710 our_current_position++;
1712 printf("S[V]A\tinsert PADDING after\n");
1713 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1714 return die_("copying metadata");
1715 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1716 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1718 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1721 printf("SV[P]A\tinsert PADDING before\n");
1722 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1723 return die_("creating PADDING block");
1724 padding->length = 17;
1725 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1726 return die_("copying metadata");
1727 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1728 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1730 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1733 printf("SV[P]PA\tinsert PADDING before\n");
1734 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1735 return die_("creating PADDING block");
1736 padding->length = 0;
1737 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1738 return die_("copying metadata");
1739 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1740 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1742 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1745 printf("SV[P]PPA\tnext\n");
1746 if(!FLAC__metadata_iterator_next(iterator))
1747 return die_("iterator ended early\n");
1748 our_current_position++;
1750 printf("SVP[P]PA\tnext\n");
1751 if(!FLAC__metadata_iterator_next(iterator))
1752 return die_("iterator ended early\n");
1753 our_current_position++;
1755 printf("SVPP[P]A\tnext\n");
1756 if(!FLAC__metadata_iterator_next(iterator))
1757 return die_("iterator ended early\n");
1758 our_current_position++;
1760 printf("SVPPP[A]\tinsert PADDING after\n");
1761 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1762 return die_("creating PADDING block");
1763 padding->length = 57;
1764 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1765 return die_("copying metadata");
1766 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1767 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1769 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1772 printf("SVPPPA[P]\tinsert PADDING before\n");
1773 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1774 return die_("creating PADDING block");
1775 padding->length = 99;
1776 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1777 return die_("copying metadata");
1778 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1779 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1781 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1784 printf("delete iterator\n");
1785 FLAC__metadata_iterator_delete(iterator);
1786 our_current_position = 0;
1788 printf("SVPPPAPP\tmerge padding\n");
1789 FLAC__metadata_chain_merge_padding(chain);
1790 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1791 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1792 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1793 delete_from_our_metadata_(7);
1794 delete_from_our_metadata_(4);
1795 delete_from_our_metadata_(3);
1797 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1798 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1799 if(!compare_chain_(chain, 0, 0))
1801 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1804 printf("SVPAP\tsort padding\n");
1805 FLAC__metadata_chain_sort_padding(chain);
1806 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1807 delete_from_our_metadata_(2);
1809 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1810 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1811 if(!compare_chain_(chain, 0, 0))
1813 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1816 printf("create iterator\n");
1817 if(0 == (iterator = FLAC__metadata_iterator_new()))
1818 return die_("allocating memory for iterator");
1820 our_current_position = 0;
1822 FLAC__metadata_iterator_init(iterator, chain);
1824 printf("[S]VAP\tnext\n");
1825 if(!FLAC__metadata_iterator_next(iterator))
1826 return die_("iterator ended early\n");
1827 our_current_position++;
1829 printf("S[V]AP\tnext\n");
1830 if(!FLAC__metadata_iterator_next(iterator))
1831 return die_("iterator ended early\n");
1832 our_current_position++;
1834 printf("SV[A]P\tdelete middle block, replace with padding\n");
1835 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1836 return die_("creating PADDING block");
1837 padding->length = 71;
1838 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1839 return die_("copying object");
1840 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1841 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1843 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1846 printf("S[V]PP\tnext\n");
1847 if(!FLAC__metadata_iterator_next(iterator))
1848 return die_("iterator ended early\n");
1849 our_current_position++;
1851 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1852 delete_from_our_metadata_(our_current_position--);
1853 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1854 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1856 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1859 printf("S[V]P\tnext\n");
1860 if(!FLAC__metadata_iterator_next(iterator))
1861 return die_("iterator ended early\n");
1862 our_current_position++;
1864 printf("SV[P]\tdelete last block, replace with padding\n");
1865 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1866 return die_("creating PADDING block");
1867 padding->length = 219;
1868 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1869 return die_("copying object");
1870 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1871 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1873 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1876 printf("S[V]P\tnext\n");
1877 if(!FLAC__metadata_iterator_next(iterator))
1878 return die_("iterator ended early\n");
1879 our_current_position++;
1881 printf("SV[P]\tdelete last block, don't replace with padding\n");
1882 delete_from_our_metadata_(our_current_position--);
1883 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1884 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1886 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1889 printf("S[V]\tprev\n");
1890 if(!FLAC__metadata_iterator_prev(iterator))
1891 return die_("iterator ended early\n");
1892 our_current_position--;
1894 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1895 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1896 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1898 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1901 printf("delete iterator\n");
1902 FLAC__metadata_iterator_delete(iterator);
1903 our_current_position = 0;
1905 printf("SV\tmerge padding\n");
1906 FLAC__metadata_chain_merge_padding(chain);
1908 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1909 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1910 if(!compare_chain_(chain, 0, 0))
1912 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1915 printf("SV\tsort padding\n");
1916 FLAC__metadata_chain_sort_padding(chain);
1918 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1919 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1920 if(!compare_chain_(chain, 0, 0))
1922 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1926 printf("delete chain\n");
1928 FLAC__metadata_chain_delete(chain);
1930 if(!remove_file_(flacfilename(is_ogg)))
1936 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1938 FLAC__Metadata_Iterator *iterator;
1939 FLAC__Metadata_Chain *chain;
1940 FLAC__IOCallbacks callbacks;
1942 memset(&callbacks, 0, sizeof(callbacks));
1943 callbacks.read = (FLAC__IOCallback_Read)fread;
1944 #ifdef FLAC__VALGRIND_TESTING
1945 callbacks.write = chain_write_cb_;
1947 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1949 callbacks.seek = chain_seek_cb_;
1950 callbacks.tell = chain_tell_cb_;
1951 callbacks.eof = chain_eof_cb_;
1953 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1955 printf("generate file\n");
1957 if(!generate_file_(/*include_extras=*/false, is_ogg))
1960 printf("create chain\n");
1962 if(0 == (chain = FLAC__metadata_chain_new()))
1963 return die_("allocating chain");
1965 printf("read chain (filename-based)\n");
1967 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1968 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1970 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1972 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1973 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1974 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1975 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1976 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1979 printf("read chain (filename-based)\n");
1981 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1982 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1984 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1986 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1987 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1988 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1989 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1990 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1993 printf("read chain (callback-based)\n");
1995 FILE *file = fopen(flacfilename(is_ogg), "rb");
1997 return die_("opening file");
1998 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2000 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2005 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2007 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2008 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2009 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2010 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2011 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2014 printf("read chain (callback-based)\n");
2016 FILE *file = fopen(flacfilename(is_ogg), "rb");
2018 return die_("opening file");
2019 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2021 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2026 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2028 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2029 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2031 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2033 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2035 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2036 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2037 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2038 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2039 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2042 printf("read chain (callback-based)\n");
2044 FILE *file = fopen(flacfilename(is_ogg), "rb");
2046 return die_("opening file");
2047 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2049 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2054 printf("create iterator\n");
2055 if(0 == (iterator = FLAC__metadata_iterator_new()))
2056 return die_("allocating memory for iterator");
2058 FLAC__metadata_iterator_init(iterator, chain);
2060 printf("[S]VP\tnext\n");
2061 if(!FLAC__metadata_iterator_next(iterator))
2062 return die_("iterator ended early\n");
2064 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2065 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2066 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2068 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2070 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2071 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2073 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2075 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2077 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2078 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2079 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2080 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2081 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2084 printf("delete iterator\n");
2086 FLAC__metadata_iterator_delete(iterator);
2088 printf("delete chain\n");
2090 FLAC__metadata_chain_delete(chain);
2092 if(!remove_file_(flacfilename(is_ogg)))
2098 FLAC__bool test_metadata_file_manipulation(void)
2100 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2102 our_metadata_.num_blocks = 0;
2104 if(!test_level_0_())
2107 if(!test_level_1_())
2110 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2112 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2114 if(!test_level_2_misc_(/*is_ogg=*/false))
2117 if(FLAC_API_SUPPORTS_OGG_FLAC) {
2118 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2120 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2123 /* when ogg flac write is supported, will have to add this: */
2124 if(!test_level_2_misc_(/*is_ogg=*/true))