1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <stdlib.h> /* for malloc() */
25 #if defined _MSC_VER || defined __MINGW32__
26 #include <sys/utime.h> /* for utime() */
27 #include <io.h> /* for chmod() */
28 #if _MSC_VER <= 1200 /* @@@ [2G limit] */
33 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
34 #include <utime.h> /* for utime() */
35 #include <unistd.h> /* for chown(), unlink() */
37 #include <sys/stat.h> /* for stat(), maybe chmod() */
38 #include "FLAC/assert.h"
39 #include "FLAC/stream_decoder.h"
40 #include "FLAC/metadata.h"
41 #include "share/grabbag.h"
42 #include "test_libs_common/file_utils_flac.h"
43 #include "test_libs_common/metadata_utils.h"
46 /******************************************************************************
47 The general strategy of these tests (for interface levels 1 and 2) is
48 to create a dummy FLAC file with a known set of initial metadata
49 blocks, then keep a mirror locally of what we expect the metadata to be
50 after each operation. Then testing becomes a simple matter of running
51 a FLAC__StreamDecoder over the dummy file after each operation, comparing
52 the decoded metadata to what's in our local copy. If there are any
53 differences in the metadata, or the actual audio data is corrupted, we
54 will catch it while decoding.
55 ******************************************************************************/
58 FLAC__bool error_occurred;
59 } decoder_client_struct;
62 FLAC__StreamMetadata *blocks[64];
64 } our_metadata_struct;
66 static const char *flacfile_ = "metadata.flac";
68 /* our copy of the metadata in flacfile_ */
69 static our_metadata_struct our_metadata_;
71 /* the current block number that corresponds to the position of the iterator we are testing */
72 static unsigned mc_our_block_number_ = 0;
74 static FLAC__bool die_(const char *msg)
76 printf("ERROR: %s\n", msg);
80 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
82 printf("ERROR: %s\n", msg);
83 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
87 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
89 printf("ERROR: %s\n", msg);
90 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
94 static void *malloc_or_die_(size_t size)
96 void *x = malloc(size);
98 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
104 static char *strdup_or_die_(const char *s)
108 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
114 /* functions for working with our metadata copy */
116 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
119 FLAC__StreamMetadata *obj = block;
120 FLAC__ASSERT(position < our_metadata_.num_blocks);
122 if(0 == (obj = FLAC__metadata_object_clone(block)))
123 return die_("during FLAC__metadata_object_clone()");
125 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
126 our_metadata_.blocks[position] = obj;
128 /* set the is_last flags */
129 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
130 our_metadata_.blocks[i]->is_last = false;
131 our_metadata_.blocks[i]->is_last = true;
136 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
139 FLAC__StreamMetadata *obj = block;
141 if(0 == (obj = FLAC__metadata_object_clone(block)))
142 return die_("during FLAC__metadata_object_clone()");
144 if(position > our_metadata_.num_blocks) {
145 position = our_metadata_.num_blocks;
148 for(i = our_metadata_.num_blocks; i > position; i--)
149 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
151 our_metadata_.blocks[position] = obj;
152 our_metadata_.num_blocks++;
154 /* set the is_last flags */
155 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
156 our_metadata_.blocks[i]->is_last = false;
157 our_metadata_.blocks[i]->is_last = true;
162 static void delete_from_our_metadata_(unsigned position)
165 FLAC__ASSERT(position < our_metadata_.num_blocks);
166 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
167 for(i = position; i < our_metadata_.num_blocks - 1; i++)
168 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
169 our_metadata_.num_blocks--;
171 /* set the is_last flags */
172 if(our_metadata_.num_blocks > 0) {
173 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
174 our_metadata_.blocks[i]->is_last = false;
175 our_metadata_.blocks[i]->is_last = true;
180 * This wad of functions supports filename- and callback-based chain reading/writing.
181 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
183 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
185 static const char *tempfile_suffix = ".metadata_edit";
187 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
189 strcpy(*tempfilename, filename);
190 strcat(*tempfilename, tempfile_suffix);
192 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
198 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
201 (void)fclose(*tempfile);
205 if(0 != *tempfilename) {
206 (void)unlink(*tempfilename);
212 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
214 FLAC__ASSERT(0 != filename);
215 FLAC__ASSERT(0 != tempfile);
216 FLAC__ASSERT(0 != tempfilename);
217 FLAC__ASSERT(0 != *tempfilename);
220 (void)fclose(*tempfile);
224 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
225 /* on some flavors of windows, rename() will fail if the destination already exists */
226 if(unlink(filename) < 0) {
227 cleanup_tempfile_(tempfile, tempfilename);
232 if(0 != rename(*tempfilename, filename)) {
233 cleanup_tempfile_(tempfile, tempfilename);
237 cleanup_tempfile_(tempfile, tempfilename);
242 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
244 FLAC__ASSERT(0 != filename);
245 FLAC__ASSERT(0 != stats);
246 return (0 == stat(filename, stats));
249 void set_file_stats_(const char *filename, struct stat *stats)
251 struct utimbuf srctime;
253 FLAC__ASSERT(0 != filename);
254 FLAC__ASSERT(0 != stats);
256 srctime.actime = stats->st_atime;
257 srctime.modtime = stats->st_mtime;
258 (void)chmod(filename, stats->st_mode);
259 (void)utime(filename, &srctime);
260 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
261 (void)chown(filename, stats->st_uid, -1);
262 (void)chown(filename, -1, stats->st_gid);
266 #ifdef FLAC__VALGRIND_TESTING
267 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
269 FILE *stream = (FILE*)handle;
270 size_t ret = fwrite(ptr, size, nmemb, stream);
277 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
279 off_t o = (off_t)offset;
280 FLAC__ASSERT(offset == o);
281 return fseeko((FILE*)handle, o, whence);
284 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
286 return ftello((FILE*)handle);
289 static int chain_eof_cb_(FLAC__IOHandle handle)
291 return feof((FILE*)handle);
294 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)
297 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
299 FLAC__IOCallbacks callbacks;
301 memset(&callbacks, 0, sizeof(callbacks));
302 callbacks.read = (FLAC__IOCallback_Read)fread;
303 #ifdef FLAC__VALGRIND_TESTING
304 callbacks.write = chain_write_cb_;
306 callbacks.write = (FLAC__IOCallback_Write)fwrite;
308 callbacks.seek = chain_seek_cb_;
309 callbacks.eof = chain_eof_cb_;
311 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
313 FILE *file, *tempfile;
315 if(preserve_file_stats) {
316 if(!get_file_stats_(filename, &stats))
319 if(0 == (file = fopen(filename, "rb")))
320 return false; /*@@@@ chain status still says OK though */
321 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
323 cleanup_tempfile_(&tempfile, &tempfilename);
324 return false; /*@@@@ chain status still says OK though */
326 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
334 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
336 if(preserve_file_stats)
337 set_file_stats_(filename, &stats);
340 FILE *file = fopen(filename, "r+b");
342 return false; /*@@@@ chain status still says OK though */
343 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
352 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
355 return FLAC__metadata_chain_read(chain, flacfile_);
357 FLAC__IOCallbacks callbacks;
359 memset(&callbacks, 0, sizeof(callbacks));
360 callbacks.read = (FLAC__IOCallback_Read)fread;
361 callbacks.seek = chain_seek_cb_;
362 callbacks.tell = chain_tell_cb_;
366 FILE *file = fopen(filename, "rb");
368 return false; /*@@@@ chain status still says OK though */
369 ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
376 /* function for comparing our metadata to a FLAC__Metadata_Chain */
378 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
381 FLAC__Metadata_Iterator *iterator;
382 FLAC__StreamMetadata *block;
383 FLAC__bool next_ok = true;
385 FLAC__ASSERT(0 != chain);
387 printf("\tcomparing chain... ");
390 if(0 == (iterator = FLAC__metadata_iterator_new()))
391 return die_("allocating memory for iterator");
393 FLAC__metadata_iterator_init(iterator, chain);
400 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
401 FLAC__metadata_iterator_delete(iterator);
402 return die_("getting block from iterator");
405 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
406 FLAC__metadata_iterator_delete(iterator);
407 return die_("metadata block mismatch");
411 next_ok = FLAC__metadata_iterator_next(iterator);
412 } while(i < our_metadata_.num_blocks && next_ok);
414 FLAC__metadata_iterator_delete(iterator);
417 return die_("chain has more blocks than expected");
419 if(i < our_metadata_.num_blocks)
420 return die_("short block count in chain");
422 if(0 != current_block) {
423 printf("CURRENT_POSITION... ");
426 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
427 return die_("metadata block mismatch");
435 /* decoder callbacks for checking the file */
437 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
439 (void)decoder, (void)buffer, (void)client_data;
442 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
443 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
445 printf("content... ");
449 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
452 /* this version pays no attention to the metadata */
453 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
455 (void)decoder, (void)metadata, (void)client_data;
457 printf("%d... ", mc_our_block_number_);
460 mc_our_block_number_++;
463 /* this version is used when we want to compare to our metadata copy */
464 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
466 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
470 /* don't bother checking if we've already hit an error */
471 if(dcd->error_occurred)
474 printf("%d... ", mc_our_block_number_);
477 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
478 (void)die_("got more metadata blocks than expected");
479 dcd->error_occurred = true;
482 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
483 (void)die_("metadata block mismatch");
484 dcd->error_occurred = true;
487 mc_our_block_number_++;
490 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
492 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
495 dcd->error_occurred = true;
496 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
499 static FLAC__bool generate_file_(FLAC__bool include_extras)
501 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
502 FLAC__StreamMetadata *metadata[4];
503 unsigned i = 0, n = 0;
505 printf("generating FLAC file for test\n");
507 while(our_metadata_.num_blocks > 0)
508 delete_from_our_metadata_(0);
510 streaminfo.is_last = false;
511 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
512 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
513 streaminfo.data.stream_info.min_blocksize = 576;
514 streaminfo.data.stream_info.max_blocksize = 576;
515 streaminfo.data.stream_info.min_framesize = 0;
516 streaminfo.data.stream_info.max_framesize = 0;
517 streaminfo.data.stream_info.sample_rate = 44100;
518 streaminfo.data.stream_info.channels = 1;
519 streaminfo.data.stream_info.bits_per_sample = 8;
520 streaminfo.data.stream_info.total_samples = 0;
521 memset(streaminfo.data.stream_info.md5sum, 0, 16);
524 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
525 vorbiscomment.is_last = false;
526 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
527 vorbiscomment.length = (4 + vendor_string_length) + 4;
528 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
529 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
530 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
531 vorbiscomment.data.vorbis_comment.num_comments = 0;
532 vorbiscomment.data.vorbis_comment.comments = 0;
536 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
537 return die_("priming our metadata");
538 cuesheet->is_last = false;
539 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
540 cuesheet->data.cue_sheet.lead_in = 123;
541 cuesheet->data.cue_sheet.is_cd = false;
542 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
543 return die_("priming our metadata");
544 cuesheet->data.cue_sheet.tracks[0].number = 1;
545 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
546 return die_("priming our metadata");
550 picture.is_last = false;
551 picture.type = FLAC__METADATA_TYPE_PICTURE;
554 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
555 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
556 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
557 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
558 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
559 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
560 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
561 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
564 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
565 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
566 picture.length += strlen(picture.data.picture.mime_type);
567 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
568 picture.length += strlen((const char *)picture.data.picture.description);
569 picture.data.picture.width = 300;
570 picture.data.picture.height = 300;
571 picture.data.picture.depth = 24;
572 picture.data.picture.colors = 0;
573 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
574 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
575 picture.length += picture.data.picture.data_length;
578 padding.is_last = true;
579 padding.type = FLAC__METADATA_TYPE_PADDING;
580 padding.length = 1234;
582 metadata[n++] = &vorbiscomment;
584 metadata[n++] = cuesheet;
585 metadata[n++] = &picture;
587 metadata[n++] = &padding;
590 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
591 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
592 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
593 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
594 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
596 return die_("priming our metadata");
598 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, n))
599 return die_("creating the encoded file");
601 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
606 static FLAC__bool test_file_(const char *filename, FLAC__StreamDecoderMetadataCallback metadata_callback)
608 FLAC__StreamDecoder *decoder;
609 decoder_client_struct decoder_client_data;
611 FLAC__ASSERT(0 != filename);
612 FLAC__ASSERT(0 != metadata_callback);
614 mc_our_block_number_ = 0;
615 decoder_client_data.error_occurred = false;
617 printf("\ttesting '%s'... ", filename);
620 if(0 == (decoder = FLAC__stream_decoder_new()))
621 return die_("couldn't allocate decoder instance");
623 FLAC__stream_decoder_set_md5_checking(decoder, true);
624 FLAC__stream_decoder_set_metadata_respond_all(decoder);
625 if(FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
626 FLAC__stream_decoder_finish(decoder);
627 FLAC__stream_decoder_delete(decoder);
628 return die_("initializing decoder\n");
630 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
631 FLAC__stream_decoder_finish(decoder);
632 FLAC__stream_decoder_delete(decoder);
633 return die_("decoding file\n");
636 FLAC__stream_decoder_finish(decoder);
637 FLAC__stream_decoder_delete(decoder);
639 if(decoder_client_data.error_occurred)
642 if(mc_our_block_number_ != our_metadata_.num_blocks)
643 return die_("short metadata block count");
649 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
651 if(!grabbag__file_change_stats(filename, read_only))
652 return die_("during grabbag__file_change_stats()");
657 static FLAC__bool remove_file_(const char *filename)
659 while(our_metadata_.num_blocks > 0)
660 delete_from_our_metadata_(0);
662 if(!grabbag__file_remove_file(filename))
663 return die_("removing file");
668 static FLAC__bool test_level_0_()
670 FLAC__StreamMetadata streaminfo;
671 FLAC__StreamMetadata *tags = 0;
672 FLAC__StreamMetadata *cuesheet = 0;
673 FLAC__StreamMetadata *picture = 0;
675 printf("\n\n++++++ testing level 0 interface\n");
677 if(!generate_file_(/*include_extras=*/true))
680 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
683 printf("testing FLAC__metadata_get_streaminfo()... ");
685 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
686 return die_("during FLAC__metadata_get_streaminfo()");
688 /* check to see if some basic data matches (c.f. generate_file_()) */
689 if(streaminfo.data.stream_info.channels != 1)
690 return die_("mismatch in streaminfo.data.stream_info.channels");
691 if(streaminfo.data.stream_info.bits_per_sample != 8)
692 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
693 if(streaminfo.data.stream_info.sample_rate != 44100)
694 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
695 if(streaminfo.data.stream_info.min_blocksize != 576)
696 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
697 if(streaminfo.data.stream_info.max_blocksize != 576)
698 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
702 printf("testing FLAC__metadata_get_tags()... ");
704 if(!FLAC__metadata_get_tags(flacfile_, &tags))
705 return die_("during FLAC__metadata_get_tags()");
707 /* check to see if some basic data matches (c.f. generate_file_()) */
708 if(tags->data.vorbis_comment.num_comments != 0)
709 return die_("mismatch in tags->data.vorbis_comment.num_comments");
713 FLAC__metadata_object_delete(tags);
715 printf("testing FLAC__metadata_get_cuesheet()... ");
717 if(!FLAC__metadata_get_cuesheet(flacfile_, &cuesheet))
718 return die_("during FLAC__metadata_get_cuesheet()");
720 /* check to see if some basic data matches (c.f. generate_file_()) */
721 if(cuesheet->data.cue_sheet.lead_in != 123)
722 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
726 FLAC__metadata_object_delete(cuesheet);
728 printf("testing FLAC__metadata_get_picture()... ");
730 if(!FLAC__metadata_get_picture(flacfile_, &picture, /*type=*/(FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1), /*max_colors=*/(unsigned)(-1)))
731 return die_("during FLAC__metadata_get_picture()");
733 /* check to see if some basic data matches (c.f. generate_file_()) */
734 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
735 return die_("mismatch in picture->data.picture.type");
739 FLAC__metadata_object_delete(picture);
741 if(!remove_file_(flacfile_))
747 static FLAC__bool test_level_1_()
749 FLAC__Metadata_SimpleIterator *iterator;
750 FLAC__StreamMetadata *block, *app, *padding;
751 FLAC__byte data[1000];
752 unsigned our_current_position = 0;
754 /* initialize 'data' to avoid Valgrind errors */
755 memset(data, 0, sizeof(data));
757 printf("\n\n++++++ testing level 1 interface\n");
759 /************************************************************/
761 printf("simple iterator on read-only file\n");
763 if(!generate_file_(/*include_extras=*/false))
766 if(!change_stats_(flacfile_, /*read_only=*/true))
769 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
772 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
773 return die_("FLAC__metadata_simple_iterator_new()");
775 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
776 return die_("FLAC__metadata_simple_iterator_init() returned false");
778 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
779 if(FLAC__metadata_simple_iterator_is_writable(iterator))
780 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
782 printf("iterate forwards\n");
784 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
785 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
786 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
787 return die_("getting block 0");
788 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
789 return die_("expected STREAMINFO type");
791 return die_("expected is_last to be false");
792 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
793 return die_("bad STREAMINFO length");
794 /* check to see if some basic data matches (c.f. generate_file_()) */
795 if(block->data.stream_info.channels != 1)
796 return die_("mismatch in channels");
797 if(block->data.stream_info.bits_per_sample != 8)
798 return die_("mismatch in bits_per_sample");
799 if(block->data.stream_info.sample_rate != 44100)
800 return die_("mismatch in sample_rate");
801 if(block->data.stream_info.min_blocksize != 576)
802 return die_("mismatch in min_blocksize");
803 if(block->data.stream_info.max_blocksize != 576)
804 return die_("mismatch in max_blocksize");
805 FLAC__metadata_object_delete(block);
807 if(!FLAC__metadata_simple_iterator_next(iterator))
808 return die_("forward iterator ended early");
809 our_current_position++;
811 if(!FLAC__metadata_simple_iterator_next(iterator))
812 return die_("forward iterator ended early");
813 our_current_position++;
815 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
816 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
817 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
818 return die_("getting block 2");
819 if(block->type != FLAC__METADATA_TYPE_PADDING)
820 return die_("expected PADDING type");
822 return die_("expected is_last to be true");
823 /* check to see if some basic data matches (c.f. generate_file_()) */
824 if(block->length != 1234)
825 return die_("bad PADDING length");
826 FLAC__metadata_object_delete(block);
828 if(FLAC__metadata_simple_iterator_next(iterator))
829 return die_("forward iterator returned true but should have returned false");
831 printf("iterate backwards\n");
832 if(!FLAC__metadata_simple_iterator_prev(iterator))
833 return die_("reverse iterator ended early");
834 if(!FLAC__metadata_simple_iterator_prev(iterator))
835 return die_("reverse iterator ended early");
836 if(FLAC__metadata_simple_iterator_prev(iterator))
837 return die_("reverse iterator returned true but should have returned false");
839 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
841 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
842 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
844 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
846 FLAC__metadata_simple_iterator_delete(iterator);
848 /************************************************************/
850 printf("simple iterator on writable file\n");
852 if(!change_stats_(flacfile_, /*read-only=*/false))
855 printf("creating APPLICATION block\n");
857 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
858 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
859 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
861 printf("creating PADDING block\n");
863 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
864 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
865 padding->length = 20;
867 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
868 return die_("FLAC__metadata_simple_iterator_new()");
870 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
871 return die_("FLAC__metadata_simple_iterator_init() returned false");
872 our_current_position = 0;
874 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
876 printf("[S]VP\ttry to write over STREAMINFO block...\n");
877 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
878 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
880 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
882 printf("[S]VP\tnext\n");
883 if(!FLAC__metadata_simple_iterator_next(iterator))
884 return die_("iterator ended early\n");
885 our_current_position++;
887 printf("S[V]P\tnext\n");
888 if(!FLAC__metadata_simple_iterator_next(iterator))
889 return die_("iterator ended early\n");
890 our_current_position++;
892 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
893 padding->length = 25;
894 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
895 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
896 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
899 printf("SVP[P]\tprev\n");
900 if(!FLAC__metadata_simple_iterator_prev(iterator))
901 return die_("iterator ended early\n");
902 our_current_position--;
904 printf("SV[P]P\tprev\n");
905 if(!FLAC__metadata_simple_iterator_prev(iterator))
906 return die_("iterator ended early\n");
907 our_current_position--;
909 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
910 padding->length = 30;
911 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
912 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
913 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
916 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
919 printf("SV[P]PP\tprev\n");
920 if(!FLAC__metadata_simple_iterator_prev(iterator))
921 return die_("iterator ended early\n");
922 our_current_position--;
924 printf("S[V]PPP\tprev\n");
925 if(!FLAC__metadata_simple_iterator_prev(iterator))
926 return die_("iterator ended early\n");
927 our_current_position--;
929 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
930 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
931 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
933 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
936 printf("[S]VPPP\tnext\n");
937 if(!FLAC__metadata_simple_iterator_next(iterator))
938 return die_("iterator ended early\n");
939 our_current_position++;
941 printf("S[V]PPP\tnext\n");
942 if(!FLAC__metadata_simple_iterator_next(iterator))
943 return die_("iterator ended early\n");
944 our_current_position++;
946 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
947 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
948 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
949 our_current_position--;
951 printf("S[V]PPP\tnext\n");
952 if(!FLAC__metadata_simple_iterator_next(iterator))
953 return die_("iterator ended early\n");
954 our_current_position++;
956 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
957 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
958 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
959 delete_from_our_metadata_(our_current_position--);
961 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
964 printf("S[V]PP\tnext\n");
965 if(!FLAC__metadata_simple_iterator_next(iterator))
966 return die_("iterator ended early\n");
967 our_current_position++;
969 printf("SV[P]P\tnext\n");
970 if(!FLAC__metadata_simple_iterator_next(iterator))
971 return die_("iterator ended early\n");
972 our_current_position++;
974 printf("SVP[P]\tdelete (last block), replace with padding\n");
975 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
976 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
977 our_current_position--;
979 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
982 printf("SV[P]P\tnext\n");
983 if(!FLAC__metadata_simple_iterator_next(iterator))
984 return die_("iterator ended early\n");
985 our_current_position++;
987 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
988 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
989 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
990 delete_from_our_metadata_(our_current_position--);
992 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
995 printf("SV[P]\tprev\n");
996 if(!FLAC__metadata_simple_iterator_prev(iterator))
997 return die_("iterator ended early\n");
998 our_current_position--;
1000 printf("S[V]P\tprev\n");
1001 if(!FLAC__metadata_simple_iterator_prev(iterator))
1002 return die_("iterator ended early\n");
1003 our_current_position--;
1005 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1006 FLAC__ASSERT(our_current_position == 0);
1007 block = FLAC__metadata_simple_iterator_get_block(iterator);
1008 block->data.stream_info.sample_rate = 32000;
1009 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1010 return die_("copying object");
1011 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1012 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1013 FLAC__metadata_object_delete(block);
1015 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1018 printf("[S]VP\tnext\n");
1019 if(!FLAC__metadata_simple_iterator_next(iterator))
1020 return die_("iterator ended early\n");
1021 our_current_position++;
1023 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1024 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1025 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1026 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1027 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1029 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1031 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1034 printf("SV[A]P\tnext\n");
1035 if(!FLAC__metadata_simple_iterator_next(iterator))
1036 return die_("iterator ended early\n");
1037 our_current_position++;
1039 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1040 app->data.application.id[0] = 'f'; /* twiddle the id */
1041 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1042 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1043 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1045 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1047 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1050 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1051 app->data.application.id[0] = 'g'; /* twiddle the id */
1052 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1053 return die_("setting APPLICATION data");
1054 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1055 return die_("copying object");
1056 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1057 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1059 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1062 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1063 app->data.application.id[0] = 'h'; /* twiddle the id */
1064 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1065 return die_("setting APPLICATION data");
1066 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1067 return die_("copying object");
1068 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1069 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1071 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1074 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1075 app->data.application.id[0] = 'i'; /* twiddle the id */
1076 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1077 return die_("setting APPLICATION data");
1078 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1079 return die_("copying object");
1080 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1081 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1082 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1084 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1087 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1088 app->data.application.id[0] = 'j'; /* twiddle the id */
1089 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1090 return die_("setting APPLICATION data");
1091 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1092 return die_("copying object");
1093 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1094 return die_("copying object");
1095 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1096 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1097 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1099 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1102 printf("SVA[A]PP\tnext\n");
1103 if(!FLAC__metadata_simple_iterator_next(iterator))
1104 return die_("iterator ended early\n");
1105 our_current_position++;
1107 printf("SVAA[P]P\tnext\n");
1108 if(!FLAC__metadata_simple_iterator_next(iterator))
1109 return die_("iterator ended early\n");
1110 our_current_position++;
1112 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1113 padding->length = 5;
1114 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1115 return die_("copying object");
1116 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1117 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1119 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1122 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1123 app->data.application.id[0] = 'k'; /* twiddle the id */
1124 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1125 return die_("copying object");
1126 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1127 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1129 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1132 printf("SVAAP[A]\tset PADDING (equal)\n");
1133 padding->length = 27;
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_(flacfile_, decoder_metadata_callback_compare_))
1142 printf("SVAAP[P]\tprev\n");
1143 if(!FLAC__metadata_simple_iterator_prev(iterator))
1144 return die_("iterator ended early\n");
1145 our_current_position--;
1147 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1148 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1149 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1150 delete_from_our_metadata_(our_current_position--);
1152 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1155 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1156 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1157 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1158 delete_from_our_metadata_(our_current_position--);
1160 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1163 printf("SV[A]P\tnext\n");
1164 if(!FLAC__metadata_simple_iterator_next(iterator))
1165 return die_("iterator ended early\n");
1166 our_current_position++;
1168 printf("SVA[P]\tinsert PADDING after\n");
1169 padding->length = 5;
1170 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1171 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1172 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1175 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1178 printf("SVAP[P]\tprev\n");
1179 if(!FLAC__metadata_simple_iterator_prev(iterator))
1180 return die_("iterator ended early\n");
1181 our_current_position--;
1183 printf("SVA[P]P\tprev\n");
1184 if(!FLAC__metadata_simple_iterator_prev(iterator))
1185 return die_("iterator ended early\n");
1186 our_current_position--;
1188 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1189 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1190 return die_("setting APPLICATION data");
1191 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1192 return die_("copying object");
1193 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1194 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1196 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1199 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1200 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1201 return die_("setting APPLICATION data");
1202 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1203 return die_("copying object");
1204 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1205 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1207 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1210 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1211 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1212 return die_("setting APPLICATION data");
1213 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1214 return die_("copying object");
1215 our_metadata_.blocks[our_current_position+1]->length = 0;
1216 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1217 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1219 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1222 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1223 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1224 return die_("setting APPLICATION data");
1225 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1226 return die_("copying object");
1227 delete_from_our_metadata_(our_current_position+1);
1228 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1229 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1231 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1234 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1235 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1236 return die_("setting APPLICATION data");
1237 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1238 return die_("copying object");
1239 delete_from_our_metadata_(our_current_position+1);
1240 our_metadata_.blocks[our_current_position]->is_last = true;
1241 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1242 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1244 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1247 printf("SV[A]\tset PADDING (equal size)\n");
1248 padding->length = app->length;
1249 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1250 return die_("copying object");
1251 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1252 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1254 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1257 printf("SV[P]\tinsert PADDING after\n");
1258 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1259 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1260 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1263 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1266 printf("SVP[P]\tinsert PADDING after\n");
1267 padding->length = 5;
1268 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1269 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1270 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1273 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1276 printf("SVPP[P]\tprev\n");
1277 if(!FLAC__metadata_simple_iterator_prev(iterator))
1278 return die_("iterator ended early\n");
1279 our_current_position--;
1281 printf("SVP[P]P\tprev\n");
1282 if(!FLAC__metadata_simple_iterator_prev(iterator))
1283 return die_("iterator ended early\n");
1284 our_current_position--;
1286 printf("SV[P]PP\tprev\n");
1287 if(!FLAC__metadata_simple_iterator_prev(iterator))
1288 return die_("iterator ended early\n");
1289 our_current_position--;
1291 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1292 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1293 return die_("setting APPLICATION data");
1294 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1295 return die_("copying object");
1296 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1297 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1299 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1302 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1303 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1304 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1305 delete_from_our_metadata_(our_current_position--);
1307 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1310 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1311 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1312 return die_("setting APPLICATION data");
1313 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1314 return die_("copying object");
1315 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1316 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1318 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1321 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1322 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1323 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1324 delete_from_our_metadata_(our_current_position--);
1326 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1329 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1330 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1331 return die_("setting APPLICATION data");
1332 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1333 return die_("copying object");
1334 delete_from_our_metadata_(our_current_position+1);
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_(flacfile_, decoder_metadata_callback_compare_))
1341 printf("SV[A]PP\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_(flacfile_, decoder_metadata_callback_compare_))
1349 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1350 if(!FLAC__metadata_object_application_set_data(app, data, 96, 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 our_metadata_.blocks[our_current_position+1]->length = 0;
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_(flacfile_, 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_(flacfile_, decoder_metadata_callback_compare_))
1369 printf("S[V]PP\tnext\n");
1370 if(!FLAC__metadata_simple_iterator_next(iterator))
1371 return die_("iterator ended early\n");
1372 our_current_position++;
1374 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1375 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1376 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1377 delete_from_our_metadata_(our_current_position--);
1379 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1382 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1383 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1384 return die_("setting APPLICATION data");
1385 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1386 return die_("copying object");
1387 delete_from_our_metadata_(our_current_position+1);
1388 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1389 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1391 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1394 printf("delete simple iterator\n");
1396 FLAC__metadata_simple_iterator_delete(iterator);
1398 FLAC__metadata_object_delete(app);
1399 FLAC__metadata_object_delete(padding);
1401 if(!remove_file_(flacfile_))
1407 static FLAC__bool test_level_2_(FLAC__bool filename_based)
1409 FLAC__Metadata_Iterator *iterator;
1410 FLAC__Metadata_Chain *chain;
1411 FLAC__StreamMetadata *block, *app, *padding;
1412 FLAC__byte data[2000];
1413 unsigned our_current_position;
1415 /* initialize 'data' to avoid Valgrind errors */
1416 memset(data, 0, sizeof(data));
1418 printf("\n\n++++++ testing level 2 interface (%s-based)\n", filename_based? "filename":"callback");
1420 printf("generate read-only file\n");
1422 if(!generate_file_(/*include_extras=*/false))
1425 if(!change_stats_(flacfile_, /*read_only=*/true))
1428 printf("create chain\n");
1430 if(0 == (chain = FLAC__metadata_chain_new()))
1431 return die_("allocating chain");
1433 printf("read chain\n");
1435 if(!read_chain_(chain, flacfile_, filename_based))
1436 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1438 printf("[S]VP\ttest initial metadata\n");
1440 if(!compare_chain_(chain, 0, 0))
1442 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1445 printf("switch file to read-write\n");
1447 if(!change_stats_(flacfile_, /*read-only=*/false))
1450 printf("create iterator\n");
1451 if(0 == (iterator = FLAC__metadata_iterator_new()))
1452 return die_("allocating memory for iterator");
1454 our_current_position = 0;
1456 FLAC__metadata_iterator_init(iterator, chain);
1458 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1459 return die_("getting block from iterator");
1461 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1463 printf("[S]VP\tmodify STREAMINFO, write\n");
1465 block->data.stream_info.sample_rate = 32000;
1466 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1467 return die_("copying object");
1469 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
1470 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1471 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1473 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1476 printf("[S]VP\tnext\n");
1477 if(!FLAC__metadata_iterator_next(iterator))
1478 return die_("iterator ended early\n");
1479 our_current_position++;
1481 printf("S[V]P\tnext\n");
1482 if(!FLAC__metadata_iterator_next(iterator))
1483 return die_("iterator ended early\n");
1484 our_current_position++;
1486 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1487 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1488 return die_("getting block from iterator");
1489 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1490 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1491 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1492 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1493 return die_("setting APPLICATION data");
1494 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1495 return die_("copying object");
1496 if(!FLAC__metadata_iterator_set_block(iterator, app))
1497 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1499 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1500 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1501 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1503 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1506 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1507 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1508 return die_("copying object");
1509 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1510 return die_("setting APPLICATION data");
1511 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1512 return die_("copying object");
1513 if(!FLAC__metadata_iterator_set_block(iterator, app))
1514 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1516 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1517 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1518 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1520 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1523 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1524 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1525 return die_("copying object");
1526 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1527 return die_("setting APPLICATION data");
1528 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1529 return die_("copying object");
1530 if(!FLAC__metadata_iterator_set_block(iterator, app))
1531 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1533 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1534 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1535 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1537 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1540 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1541 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1542 return die_("copying object");
1543 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1544 return die_("setting APPLICATION data");
1545 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1546 return die_("copying object");
1547 if(!FLAC__metadata_iterator_set_block(iterator, app))
1548 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1550 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1551 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1552 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1554 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1557 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1558 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1559 return die_("copying object");
1560 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1561 return die_("setting APPLICATION data");
1562 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1563 return die_("copying object");
1564 if(!FLAC__metadata_iterator_set_block(iterator, app))
1565 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1567 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1568 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1569 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1571 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1574 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1575 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1576 return die_("creating PADDING block");
1577 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1578 return die_("copying object");
1579 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1580 return die_("setting APPLICATION data");
1581 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1582 return die_("copying object");
1583 padding->length = 0;
1584 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1585 return die_("internal error");
1586 if(!FLAC__metadata_iterator_set_block(iterator, app))
1587 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1589 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1590 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1591 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1593 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1596 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1597 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1598 return die_("copying object");
1599 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1600 return die_("setting APPLICATION data");
1601 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1602 return die_("copying object");
1603 our_metadata_.blocks[our_current_position+1]->length = 13;
1604 if(!FLAC__metadata_iterator_set_block(iterator, app))
1605 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1607 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1608 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1609 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1611 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1614 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1615 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1616 return die_("copying object");
1617 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1618 return die_("setting APPLICATION data");
1619 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1620 return die_("copying object");
1621 if(!FLAC__metadata_iterator_set_block(iterator, app))
1622 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1624 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1625 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1626 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1628 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1631 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1632 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1633 return die_("copying object");
1634 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1635 return die_("setting APPLICATION data");
1636 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1637 return die_("copying object");
1638 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1639 if(!FLAC__metadata_iterator_set_block(iterator, app))
1640 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1642 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1643 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1644 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1646 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1649 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1650 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1651 return die_("copying object");
1652 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1653 return die_("setting APPLICATION data");
1654 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1655 return die_("copying object");
1656 delete_from_our_metadata_(our_current_position+1);
1657 if(!FLAC__metadata_iterator_set_block(iterator, app))
1658 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1660 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1661 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1662 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1664 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1667 printf("SV[A]\tprev\n");
1668 if(!FLAC__metadata_iterator_prev(iterator))
1669 return die_("iterator ended early\n");
1670 our_current_position--;
1672 printf("S[V]A\tprev\n");
1673 if(!FLAC__metadata_iterator_prev(iterator))
1674 return die_("iterator ended early\n");
1675 our_current_position--;
1677 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1678 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1679 return die_("creating PADDING block");
1680 padding->length = 30;
1681 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1682 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1684 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1686 printf("[S]VP\tnext\n");
1687 if(!FLAC__metadata_iterator_next(iterator))
1688 return die_("iterator ended early\n");
1689 our_current_position++;
1691 printf("S[V]A\tinsert PADDING after\n");
1692 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1693 return die_("copying metadata");
1694 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1695 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1697 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1700 printf("SV[P]A\tinsert PADDING before\n");
1701 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1702 return die_("creating PADDING block");
1703 padding->length = 17;
1704 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1705 return die_("copying metadata");
1706 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1707 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1709 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1712 printf("SV[P]PA\tinsert PADDING before\n");
1713 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1714 return die_("creating PADDING block");
1715 padding->length = 0;
1716 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1717 return die_("copying metadata");
1718 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1719 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1721 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1724 printf("SV[P]PPA\tnext\n");
1725 if(!FLAC__metadata_iterator_next(iterator))
1726 return die_("iterator ended early\n");
1727 our_current_position++;
1729 printf("SVP[P]PA\tnext\n");
1730 if(!FLAC__metadata_iterator_next(iterator))
1731 return die_("iterator ended early\n");
1732 our_current_position++;
1734 printf("SVPP[P]A\tnext\n");
1735 if(!FLAC__metadata_iterator_next(iterator))
1736 return die_("iterator ended early\n");
1737 our_current_position++;
1739 printf("SVPPP[A]\tinsert PADDING after\n");
1740 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1741 return die_("creating PADDING block");
1742 padding->length = 57;
1743 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1744 return die_("copying metadata");
1745 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1746 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1748 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1751 printf("SVPPPA[P]\tinsert PADDING before\n");
1752 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1753 return die_("creating PADDING block");
1754 padding->length = 99;
1755 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1756 return die_("copying metadata");
1757 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1758 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1760 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1763 printf("delete iterator\n");
1764 FLAC__metadata_iterator_delete(iterator);
1765 our_current_position = 0;
1767 printf("SVPPPAPP\tmerge padding\n");
1768 FLAC__metadata_chain_merge_padding(chain);
1769 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1770 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1771 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1772 delete_from_our_metadata_(7);
1773 delete_from_our_metadata_(4);
1774 delete_from_our_metadata_(3);
1776 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1777 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1778 if(!compare_chain_(chain, 0, 0))
1780 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1783 printf("SVPAP\tsort padding\n");
1784 FLAC__metadata_chain_sort_padding(chain);
1785 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1786 delete_from_our_metadata_(2);
1788 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
1789 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1790 if(!compare_chain_(chain, 0, 0))
1792 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1795 printf("create iterator\n");
1796 if(0 == (iterator = FLAC__metadata_iterator_new()))
1797 return die_("allocating memory for iterator");
1799 our_current_position = 0;
1801 FLAC__metadata_iterator_init(iterator, chain);
1803 printf("[S]VAP\tnext\n");
1804 if(!FLAC__metadata_iterator_next(iterator))
1805 return die_("iterator ended early\n");
1806 our_current_position++;
1808 printf("S[V]AP\tnext\n");
1809 if(!FLAC__metadata_iterator_next(iterator))
1810 return die_("iterator ended early\n");
1811 our_current_position++;
1813 printf("SV[A]P\tdelete middle block, replace with padding\n");
1814 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1815 return die_("creating PADDING block");
1816 padding->length = 71;
1817 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1818 return die_("copying object");
1819 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1820 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1822 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1825 printf("S[V]PP\tnext\n");
1826 if(!FLAC__metadata_iterator_next(iterator))
1827 return die_("iterator ended early\n");
1828 our_current_position++;
1830 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1831 delete_from_our_metadata_(our_current_position--);
1832 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1833 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1835 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1838 printf("S[V]P\tnext\n");
1839 if(!FLAC__metadata_iterator_next(iterator))
1840 return die_("iterator ended early\n");
1841 our_current_position++;
1843 printf("SV[P]\tdelete last block, replace with padding\n");
1844 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1845 return die_("creating PADDING block");
1846 padding->length = 219;
1847 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1848 return die_("copying object");
1849 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1850 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1852 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1855 printf("S[V]P\tnext\n");
1856 if(!FLAC__metadata_iterator_next(iterator))
1857 return die_("iterator ended early\n");
1858 our_current_position++;
1860 printf("SV[P]\tdelete last block, don't replace with padding\n");
1861 delete_from_our_metadata_(our_current_position--);
1862 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1863 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1865 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1868 printf("S[V]\tprev\n");
1869 if(!FLAC__metadata_iterator_prev(iterator))
1870 return die_("iterator ended early\n");
1871 our_current_position--;
1873 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1874 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1875 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1877 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1880 printf("delete iterator\n");
1881 FLAC__metadata_iterator_delete(iterator);
1882 our_current_position = 0;
1884 printf("SV\tmerge padding\n");
1885 FLAC__metadata_chain_merge_padding(chain);
1887 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1888 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1889 if(!compare_chain_(chain, 0, 0))
1891 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1894 printf("SV\tsort padding\n");
1895 FLAC__metadata_chain_sort_padding(chain);
1897 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
1898 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1899 if(!compare_chain_(chain, 0, 0))
1901 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1904 printf("delete chain\n");
1906 FLAC__metadata_chain_delete(chain);
1908 if(!remove_file_(flacfile_))
1914 static FLAC__bool test_level_2_misc_()
1916 FLAC__Metadata_Iterator *iterator;
1917 FLAC__Metadata_Chain *chain;
1918 FLAC__IOCallbacks callbacks;
1920 memset(&callbacks, 0, sizeof(callbacks));
1921 callbacks.read = (FLAC__IOCallback_Read)fread;
1922 #ifdef FLAC__VALGRIND_TESTING
1923 callbacks.write = chain_write_cb_;
1925 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1927 callbacks.seek = chain_seek_cb_;
1928 callbacks.tell = chain_tell_cb_;
1929 callbacks.eof = chain_eof_cb_;
1931 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1933 printf("generate file\n");
1935 if(!generate_file_(/*include_extras=*/false))
1938 printf("create chain\n");
1940 if(0 == (chain = FLAC__metadata_chain_new()))
1941 return die_("allocating chain");
1943 printf("read chain (filename-based)\n");
1945 if(!FLAC__metadata_chain_read(chain, flacfile_))
1946 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1948 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1950 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1951 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1952 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1953 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1954 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1957 printf("read chain (filename-based)\n");
1959 if(!FLAC__metadata_chain_read(chain, flacfile_))
1960 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1962 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1964 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1965 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1966 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1967 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1968 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1971 printf("read chain (callback-based)\n");
1973 FILE *file = fopen(flacfile_, "rb");
1975 return die_("opening file");
1976 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1978 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1983 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
1985 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1986 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1987 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1988 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1989 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1992 printf("read chain (callback-based)\n");
1994 FILE *file = fopen(flacfile_, "rb");
1996 return die_("opening file");
1997 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1999 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2004 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2006 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2007 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2009 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2011 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2013 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2014 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2015 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2016 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2017 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2020 printf("read chain (callback-based)\n");
2022 FILE *file = fopen(flacfile_, "rb");
2024 return die_("opening file");
2025 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2027 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2032 printf("create iterator\n");
2033 if(0 == (iterator = FLAC__metadata_iterator_new()))
2034 return die_("allocating memory for iterator");
2036 FLAC__metadata_iterator_init(iterator, chain);
2038 printf("[S]VP\tnext\n");
2039 if(!FLAC__metadata_iterator_next(iterator))
2040 return die_("iterator ended early\n");
2042 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2043 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2044 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2046 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2048 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2049 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2051 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2053 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2055 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2056 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2057 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2058 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2059 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2062 printf("delete iterator\n");
2064 FLAC__metadata_iterator_delete(iterator);
2066 printf("delete chain\n");
2068 FLAC__metadata_chain_delete(chain);
2070 if(!remove_file_(flacfile_))
2076 FLAC__bool test_metadata_file_manipulation()
2078 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2080 our_metadata_.num_blocks = 0;
2082 if(!test_level_0_())
2085 if(!test_level_1_())
2088 if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
2090 if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
2092 if(!test_level_2_misc_())