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() */
29 #if _MSC_VER <= 1600 /* @@@ [2G limit] */
38 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
39 #include <utime.h> /* for utime() */
40 #include <unistd.h> /* for chown(), unlink() */
42 #include <sys/stat.h> /* for stat(), maybe chmod() */
43 #include "FLAC/assert.h"
44 #include "FLAC/stream_decoder.h"
45 #include "FLAC/metadata.h"
46 #include "share/grabbag.h"
47 #include "test_libs_common/file_utils_flac.h"
48 #include "test_libs_common/metadata_utils.h"
52 /******************************************************************************
53 The general strategy of these tests (for interface levels 1 and 2) is
54 to create a dummy FLAC file with a known set of initial metadata
55 blocks, then keep a mirror locally of what we expect the metadata to be
56 after each operation. Then testing becomes a simple matter of running
57 a FLAC__StreamDecoder over the dummy file after each operation, comparing
58 the decoded metadata to what's in our local copy. If there are any
59 differences in the metadata, or the actual audio data is corrupted, we
60 will catch it while decoding.
61 ******************************************************************************/
64 FLAC__bool error_occurred;
65 } decoder_client_struct;
68 FLAC__StreamMetadata *blocks[64];
70 } our_metadata_struct;
72 /* our copy of the metadata in flacfilename() */
73 static our_metadata_struct our_metadata_;
75 /* the current block number that corresponds to the position of the iterator we are testing */
76 static unsigned mc_our_block_number_ = 0;
78 static const char *flacfilename(FLAC__bool is_ogg)
80 return is_ogg? "metadata.oga" : "metadata.flac";
83 static FLAC__bool die_(const char *msg)
85 printf("ERROR: %s\n", msg);
89 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
91 printf("ERROR: %s\n", msg);
92 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
96 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
98 printf("ERROR: %s\n", msg);
99 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
103 static void *malloc_or_die_(size_t size)
105 void *x = malloc(size);
107 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
113 static char *strdup_or_die_(const char *s)
117 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
123 /* functions for working with our metadata copy */
125 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
128 FLAC__StreamMetadata *obj = block;
129 FLAC__ASSERT(position < our_metadata_.num_blocks);
131 if(0 == (obj = FLAC__metadata_object_clone(block)))
132 return die_("during FLAC__metadata_object_clone()");
134 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
135 our_metadata_.blocks[position] = obj;
137 /* set the is_last flags */
138 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
139 our_metadata_.blocks[i]->is_last = false;
140 our_metadata_.blocks[i]->is_last = true;
145 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
148 FLAC__StreamMetadata *obj = block;
150 if(0 == (obj = FLAC__metadata_object_clone(block)))
151 return die_("during FLAC__metadata_object_clone()");
153 if(position > our_metadata_.num_blocks) {
154 position = our_metadata_.num_blocks;
157 for(i = our_metadata_.num_blocks; i > position; i--)
158 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
160 our_metadata_.blocks[position] = obj;
161 our_metadata_.num_blocks++;
163 /* set the is_last flags */
164 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
165 our_metadata_.blocks[i]->is_last = false;
166 our_metadata_.blocks[i]->is_last = true;
171 static void delete_from_our_metadata_(unsigned position)
174 FLAC__ASSERT(position < our_metadata_.num_blocks);
175 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
176 for(i = position; i < our_metadata_.num_blocks - 1; i++)
177 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
178 our_metadata_.num_blocks--;
180 /* set the is_last flags */
181 if(our_metadata_.num_blocks > 0) {
182 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
183 our_metadata_.blocks[i]->is_last = false;
184 our_metadata_.blocks[i]->is_last = true;
189 * This wad of functions supports filename- and callback-based chain reading/writing.
190 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
192 static FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
194 static const char *tempfile_suffix = ".metadata_edit";
196 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
198 strcpy(*tempfilename, filename);
199 strcat(*tempfilename, tempfile_suffix);
201 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
207 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
210 (void)fclose(*tempfile);
214 if(0 != *tempfilename) {
215 (void)unlink(*tempfilename);
221 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
223 FLAC__ASSERT(0 != filename);
224 FLAC__ASSERT(0 != tempfile);
225 FLAC__ASSERT(0 != tempfilename);
226 FLAC__ASSERT(0 != *tempfilename);
229 (void)fclose(*tempfile);
233 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
234 /* on some flavors of windows, rename() will fail if the destination already exists */
235 if(unlink(filename) < 0) {
236 cleanup_tempfile_(tempfile, tempfilename);
241 if(0 != rename(*tempfilename, filename)) {
242 cleanup_tempfile_(tempfile, tempfilename);
246 cleanup_tempfile_(tempfile, tempfilename);
251 static FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
253 FLAC__ASSERT(0 != filename);
254 FLAC__ASSERT(0 != stats);
255 return (0 == stat(filename, stats));
258 static void set_file_stats_(const char *filename, struct stat *stats)
260 struct utimbuf srctime;
262 FLAC__ASSERT(0 != filename);
263 FLAC__ASSERT(0 != stats);
265 srctime.actime = stats->st_atime;
266 srctime.modtime = stats->st_mtime;
267 (void)chmod(filename, stats->st_mode);
268 (void)utime(filename, &srctime);
269 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
270 (void)chown(filename, stats->st_uid, -1);
271 (void)chown(filename, -1, stats->st_gid);
275 #ifdef FLAC__VALGRIND_TESTING
276 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
278 FILE *stream = (FILE*)handle;
279 size_t ret = fwrite(ptr, size, nmemb, stream);
286 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
288 off_t o = (off_t)offset;
289 FLAC__ASSERT(offset == o);
290 return fseeko((FILE*)handle, o, whence);
293 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
295 return ftello((FILE*)handle);
298 static int chain_eof_cb_(FLAC__IOHandle handle)
300 return feof((FILE*)handle);
303 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)
306 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
308 FLAC__IOCallbacks callbacks;
310 memset(&callbacks, 0, sizeof(callbacks));
311 callbacks.read = (FLAC__IOCallback_Read)fread;
312 #ifdef FLAC__VALGRIND_TESTING
313 callbacks.write = chain_write_cb_;
315 callbacks.write = (FLAC__IOCallback_Write)fwrite;
317 callbacks.seek = chain_seek_cb_;
318 callbacks.eof = chain_eof_cb_;
320 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
322 FILE *file, *tempfile = 0;
324 if(preserve_file_stats) {
325 if(!get_file_stats_(filename, &stats))
328 if(0 == (file = fopen(filename, "rb")))
329 return false; /*@@@@ chain status still says OK though */
330 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
332 cleanup_tempfile_(&tempfile, &tempfilename);
333 return false; /*@@@@ chain status still says OK though */
335 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
343 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
345 if(preserve_file_stats)
346 set_file_stats_(filename, &stats);
349 FILE *file = fopen(filename, "r+b");
351 return false; /*@@@@ chain status still says OK though */
352 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
361 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based, FLAC__bool is_ogg)
365 FLAC__metadata_chain_read_ogg(chain, flacfilename(is_ogg)) :
366 FLAC__metadata_chain_read(chain, flacfilename(is_ogg))
369 FLAC__IOCallbacks callbacks;
371 memset(&callbacks, 0, sizeof(callbacks));
372 callbacks.read = (FLAC__IOCallback_Read)fread;
373 callbacks.seek = chain_seek_cb_;
374 callbacks.tell = chain_tell_cb_;
378 FILE *file = fopen(filename, "rb");
380 return false; /*@@@@ chain status still says OK though */
382 FLAC__metadata_chain_read_ogg_with_callbacks(chain, (FLAC__IOHandle)file, callbacks) :
383 FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)
391 /* function for comparing our metadata to a FLAC__Metadata_Chain */
393 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
396 FLAC__Metadata_Iterator *iterator;
397 FLAC__StreamMetadata *block;
398 FLAC__bool next_ok = true;
400 FLAC__ASSERT(0 != chain);
402 printf("\tcomparing chain... ");
405 if(0 == (iterator = FLAC__metadata_iterator_new()))
406 return die_("allocating memory for iterator");
408 FLAC__metadata_iterator_init(iterator, chain);
415 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
416 FLAC__metadata_iterator_delete(iterator);
417 return die_("getting block from iterator");
420 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
421 FLAC__metadata_iterator_delete(iterator);
422 return die_("metadata block mismatch");
426 next_ok = FLAC__metadata_iterator_next(iterator);
427 } while(i < our_metadata_.num_blocks && next_ok);
429 FLAC__metadata_iterator_delete(iterator);
432 return die_("chain has more blocks than expected");
434 if(i < our_metadata_.num_blocks)
435 return die_("short block count in chain");
437 if(0 != current_block) {
438 printf("CURRENT_POSITION... ");
441 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
442 return die_("metadata block mismatch");
450 /* decoder callbacks for checking the file */
452 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
454 (void)decoder, (void)buffer, (void)client_data;
457 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
458 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
460 printf("content... ");
464 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
467 /* this version pays no attention to the metadata */
468 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
470 (void)decoder, (void)metadata, (void)client_data;
472 printf("%d... ", mc_our_block_number_);
475 mc_our_block_number_++;
478 /* this version is used when we want to compare to our metadata copy */
479 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
481 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
485 /* don't bother checking if we've already hit an error */
486 if(dcd->error_occurred)
489 printf("%d... ", mc_our_block_number_);
492 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
493 (void)die_("got more metadata blocks than expected");
494 dcd->error_occurred = true;
497 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
498 (void)die_("metadata block mismatch");
499 dcd->error_occurred = true;
502 mc_our_block_number_++;
505 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
507 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
510 dcd->error_occurred = true;
511 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
514 static FLAC__bool generate_file_(FLAC__bool include_extras, FLAC__bool is_ogg)
516 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
517 FLAC__StreamMetadata *metadata[4];
518 unsigned i = 0, n = 0;
520 printf("generating %sFLAC file for test\n", is_ogg? "Ogg " : "");
522 while(our_metadata_.num_blocks > 0)
523 delete_from_our_metadata_(0);
525 streaminfo.is_last = false;
526 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
527 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
528 streaminfo.data.stream_info.min_blocksize = 576;
529 streaminfo.data.stream_info.max_blocksize = 576;
530 streaminfo.data.stream_info.min_framesize = 0;
531 streaminfo.data.stream_info.max_framesize = 0;
532 streaminfo.data.stream_info.sample_rate = 44100;
533 streaminfo.data.stream_info.channels = 1;
534 streaminfo.data.stream_info.bits_per_sample = 8;
535 streaminfo.data.stream_info.total_samples = 0;
536 memset(streaminfo.data.stream_info.md5sum, 0, 16);
539 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
540 vorbiscomment.is_last = false;
541 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
542 vorbiscomment.length = (4 + vendor_string_length) + 4;
543 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
544 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
545 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
546 vorbiscomment.data.vorbis_comment.num_comments = 0;
547 vorbiscomment.data.vorbis_comment.comments = 0;
551 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
552 return die_("priming our metadata");
553 cuesheet->is_last = false;
554 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
555 cuesheet->data.cue_sheet.lead_in = 123;
556 cuesheet->data.cue_sheet.is_cd = false;
557 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
558 return die_("priming our metadata");
559 cuesheet->data.cue_sheet.tracks[0].number = 1;
560 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
561 return die_("priming our metadata");
565 picture.is_last = false;
566 picture.type = FLAC__METADATA_TYPE_PICTURE;
569 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
570 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
571 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
572 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
573 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
574 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
575 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
576 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
579 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
580 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
581 picture.length += strlen(picture.data.picture.mime_type);
582 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
583 picture.length += strlen((const char *)picture.data.picture.description);
584 picture.data.picture.width = 300;
585 picture.data.picture.height = 300;
586 picture.data.picture.depth = 24;
587 picture.data.picture.colors = 0;
588 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
589 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
590 picture.length += picture.data.picture.data_length;
593 padding.is_last = true;
594 padding.type = FLAC__METADATA_TYPE_PADDING;
595 padding.length = 1234;
597 metadata[n++] = &vorbiscomment;
599 metadata[n++] = cuesheet;
600 metadata[n++] = &picture;
602 metadata[n++] = &padding;
605 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
606 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
607 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
608 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
609 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
611 return die_("priming our metadata");
613 if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), 0, 512 * 1024, &streaminfo, metadata, n))
614 return die_("creating the encoded file");
616 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
617 free(picture.data.picture.mime_type);
618 free(picture.data.picture.description);
619 free(picture.data.picture.data);
621 FLAC__metadata_object_delete(cuesheet);
626 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
628 const char *filename = flacfilename(is_ogg);
629 FLAC__StreamDecoder *decoder;
630 decoder_client_struct decoder_client_data;
632 FLAC__ASSERT(0 != metadata_callback);
634 mc_our_block_number_ = 0;
635 decoder_client_data.error_occurred = false;
637 printf("\ttesting '%s'... ", filename);
640 if(0 == (decoder = FLAC__stream_decoder_new()))
641 return die_("couldn't allocate decoder instance");
643 FLAC__stream_decoder_set_md5_checking(decoder, true);
644 FLAC__stream_decoder_set_metadata_respond_all(decoder);
647 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
648 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
649 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
651 (void)FLAC__stream_decoder_finish(decoder);
652 FLAC__stream_decoder_delete(decoder);
653 return die_("initializing decoder\n");
655 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
656 (void)FLAC__stream_decoder_finish(decoder);
657 FLAC__stream_decoder_delete(decoder);
658 return die_("decoding file\n");
661 (void)FLAC__stream_decoder_finish(decoder);
662 FLAC__stream_decoder_delete(decoder);
664 if(decoder_client_data.error_occurred)
667 if(mc_our_block_number_ != our_metadata_.num_blocks)
668 return die_("short metadata block count");
674 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
676 if(!grabbag__file_change_stats(filename, read_only))
677 return die_("during grabbag__file_change_stats()");
682 static FLAC__bool remove_file_(const char *filename)
684 while(our_metadata_.num_blocks > 0)
685 delete_from_our_metadata_(0);
687 if(!grabbag__file_remove_file(filename))
688 return die_("removing file");
693 static FLAC__bool test_level_0_(void)
695 FLAC__StreamMetadata streaminfo;
696 FLAC__StreamMetadata *tags = 0;
697 FLAC__StreamMetadata *cuesheet = 0;
698 FLAC__StreamMetadata *picture = 0;
700 printf("\n\n++++++ testing level 0 interface\n");
702 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
705 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
708 printf("testing FLAC__metadata_get_streaminfo()... ");
710 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
711 return die_("during FLAC__metadata_get_streaminfo()");
713 /* check to see if some basic data matches (c.f. generate_file_()) */
714 if(streaminfo.data.stream_info.channels != 1)
715 return die_("mismatch in streaminfo.data.stream_info.channels");
716 if(streaminfo.data.stream_info.bits_per_sample != 8)
717 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
718 if(streaminfo.data.stream_info.sample_rate != 44100)
719 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
720 if(streaminfo.data.stream_info.min_blocksize != 576)
721 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
722 if(streaminfo.data.stream_info.max_blocksize != 576)
723 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
727 printf("testing FLAC__metadata_get_tags()... ");
729 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
730 return die_("during FLAC__metadata_get_tags()");
732 /* check to see if some basic data matches (c.f. generate_file_()) */
733 if(tags->data.vorbis_comment.num_comments != 0)
734 return die_("mismatch in tags->data.vorbis_comment.num_comments");
738 FLAC__metadata_object_delete(tags);
740 printf("testing FLAC__metadata_get_cuesheet()... ");
742 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
743 return die_("during FLAC__metadata_get_cuesheet()");
745 /* check to see if some basic data matches (c.f. generate_file_()) */
746 if(cuesheet->data.cue_sheet.lead_in != 123)
747 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
751 FLAC__metadata_object_delete(cuesheet);
753 printf("testing FLAC__metadata_get_picture()... ");
755 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)))
756 return die_("during FLAC__metadata_get_picture()");
758 /* check to see if some basic data matches (c.f. generate_file_()) */
759 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
760 return die_("mismatch in picture->data.picture.type");
764 FLAC__metadata_object_delete(picture);
766 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
772 static FLAC__bool test_level_1_(void)
774 FLAC__Metadata_SimpleIterator *iterator;
775 FLAC__StreamMetadata *block, *app, *padding;
776 FLAC__byte data[1000];
777 unsigned our_current_position = 0;
779 /* initialize 'data' to avoid Valgrind errors */
780 memset(data, 0, sizeof(data));
782 printf("\n\n++++++ testing level 1 interface\n");
784 /************************************************************/
786 printf("simple iterator on read-only file\n");
788 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
791 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
794 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
797 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
798 return die_("FLAC__metadata_simple_iterator_new()");
800 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
801 return die_("FLAC__metadata_simple_iterator_init() returned false");
803 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
804 if(FLAC__metadata_simple_iterator_is_writable(iterator))
805 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
807 printf("iterate forwards\n");
809 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
810 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
811 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
812 return die_("getting block 0");
813 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
814 return die_("expected STREAMINFO type");
816 return die_("expected is_last to be false");
817 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
818 return die_("bad STREAMINFO length");
819 /* check to see if some basic data matches (c.f. generate_file_()) */
820 if(block->data.stream_info.channels != 1)
821 return die_("mismatch in channels");
822 if(block->data.stream_info.bits_per_sample != 8)
823 return die_("mismatch in bits_per_sample");
824 if(block->data.stream_info.sample_rate != 44100)
825 return die_("mismatch in sample_rate");
826 if(block->data.stream_info.min_blocksize != 576)
827 return die_("mismatch in min_blocksize");
828 if(block->data.stream_info.max_blocksize != 576)
829 return die_("mismatch in max_blocksize");
830 FLAC__metadata_object_delete(block);
832 if(!FLAC__metadata_simple_iterator_next(iterator))
833 return die_("forward iterator ended early");
834 our_current_position++;
836 if(!FLAC__metadata_simple_iterator_next(iterator))
837 return die_("forward iterator ended early");
838 our_current_position++;
840 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
841 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
842 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
843 return die_("getting block 2");
844 if(block->type != FLAC__METADATA_TYPE_PADDING)
845 return die_("expected PADDING type");
847 return die_("expected is_last to be true");
848 /* check to see if some basic data matches (c.f. generate_file_()) */
849 if(block->length != 1234)
850 return die_("bad PADDING length");
851 FLAC__metadata_object_delete(block);
853 if(FLAC__metadata_simple_iterator_next(iterator))
854 return die_("forward iterator returned true but should have returned false");
856 printf("iterate backwards\n");
857 if(!FLAC__metadata_simple_iterator_prev(iterator))
858 return die_("reverse iterator ended early");
859 if(!FLAC__metadata_simple_iterator_prev(iterator))
860 return die_("reverse iterator ended early");
861 if(FLAC__metadata_simple_iterator_prev(iterator))
862 return die_("reverse iterator returned true but should have returned false");
864 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
866 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
867 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
869 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
871 FLAC__metadata_simple_iterator_delete(iterator);
873 /************************************************************/
875 printf("simple iterator on writable file\n");
877 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
880 printf("creating APPLICATION block\n");
882 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
883 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
884 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
886 printf("creating PADDING block\n");
888 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
889 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
890 padding->length = 20;
892 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
893 return die_("FLAC__metadata_simple_iterator_new()");
895 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
896 return die_("FLAC__metadata_simple_iterator_init() returned false");
897 our_current_position = 0;
899 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
901 printf("[S]VP\ttry to write over STREAMINFO block...\n");
902 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
903 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
905 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
907 printf("[S]VP\tnext\n");
908 if(!FLAC__metadata_simple_iterator_next(iterator))
909 return die_("iterator ended early\n");
910 our_current_position++;
912 printf("S[V]P\tnext\n");
913 if(!FLAC__metadata_simple_iterator_next(iterator))
914 return die_("iterator ended early\n");
915 our_current_position++;
917 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
918 padding->length = 25;
919 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
920 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
921 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
924 printf("SVP[P]\tprev\n");
925 if(!FLAC__metadata_simple_iterator_prev(iterator))
926 return die_("iterator ended early\n");
927 our_current_position--;
929 printf("SV[P]P\tprev\n");
930 if(!FLAC__metadata_simple_iterator_prev(iterator))
931 return die_("iterator ended early\n");
932 our_current_position--;
934 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
935 padding->length = 30;
936 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
937 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
938 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
941 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
944 printf("SV[P]PP\tprev\n");
945 if(!FLAC__metadata_simple_iterator_prev(iterator))
946 return die_("iterator ended early\n");
947 our_current_position--;
949 printf("S[V]PPP\tprev\n");
950 if(!FLAC__metadata_simple_iterator_prev(iterator))
951 return die_("iterator ended early\n");
952 our_current_position--;
954 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
955 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
956 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
958 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
961 printf("[S]VPPP\tnext\n");
962 if(!FLAC__metadata_simple_iterator_next(iterator))
963 return die_("iterator ended early\n");
964 our_current_position++;
966 printf("S[V]PPP\tnext\n");
967 if(!FLAC__metadata_simple_iterator_next(iterator))
968 return die_("iterator ended early\n");
969 our_current_position++;
971 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
972 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
973 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
974 our_current_position--;
976 printf("S[V]PPP\tnext\n");
977 if(!FLAC__metadata_simple_iterator_next(iterator))
978 return die_("iterator ended early\n");
979 our_current_position++;
981 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
982 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
983 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
984 delete_from_our_metadata_(our_current_position--);
986 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
989 printf("S[V]PP\tnext\n");
990 if(!FLAC__metadata_simple_iterator_next(iterator))
991 return die_("iterator ended early\n");
992 our_current_position++;
994 printf("SV[P]P\tnext\n");
995 if(!FLAC__metadata_simple_iterator_next(iterator))
996 return die_("iterator ended early\n");
997 our_current_position++;
999 printf("SVP[P]\tdelete (last block), replace with padding\n");
1000 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
1001 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1002 our_current_position--;
1004 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1007 printf("SV[P]P\tnext\n");
1008 if(!FLAC__metadata_simple_iterator_next(iterator))
1009 return die_("iterator ended early\n");
1010 our_current_position++;
1012 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1013 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1014 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1015 delete_from_our_metadata_(our_current_position--);
1017 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1020 printf("SV[P]\tprev\n");
1021 if(!FLAC__metadata_simple_iterator_prev(iterator))
1022 return die_("iterator ended early\n");
1023 our_current_position--;
1025 printf("S[V]P\tprev\n");
1026 if(!FLAC__metadata_simple_iterator_prev(iterator))
1027 return die_("iterator ended early\n");
1028 our_current_position--;
1030 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1031 FLAC__ASSERT(our_current_position == 0);
1032 block = FLAC__metadata_simple_iterator_get_block(iterator);
1033 block->data.stream_info.sample_rate = 32000;
1034 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1035 return die_("copying object");
1036 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1037 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1038 FLAC__metadata_object_delete(block);
1040 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1043 printf("[S]VP\tnext\n");
1044 if(!FLAC__metadata_simple_iterator_next(iterator))
1045 return die_("iterator ended early\n");
1046 our_current_position++;
1048 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1049 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1050 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1051 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1052 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1054 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1056 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1059 printf("SV[A]P\tnext\n");
1060 if(!FLAC__metadata_simple_iterator_next(iterator))
1061 return die_("iterator ended early\n");
1062 our_current_position++;
1064 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1065 app->data.application.id[0] = 'f'; /* twiddle the id */
1066 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1067 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1068 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1070 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1072 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1075 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1076 app->data.application.id[0] = 'g'; /* twiddle the id */
1077 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1078 return die_("setting APPLICATION data");
1079 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1080 return die_("copying object");
1081 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1082 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1084 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1087 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1088 app->data.application.id[0] = 'h'; /* twiddle the id */
1089 if(!FLAC__metadata_object_application_set_data(app, data, 12, 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(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1094 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1096 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1099 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1100 app->data.application.id[0] = 'i'; /* twiddle the id */
1101 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1102 return die_("setting APPLICATION data");
1103 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1104 return die_("copying object");
1105 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1106 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1107 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1109 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1112 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1113 app->data.application.id[0] = 'j'; /* twiddle the id */
1114 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1115 return die_("setting APPLICATION data");
1116 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1117 return die_("copying object");
1118 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1119 return die_("copying object");
1120 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1121 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1122 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1124 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1127 printf("SVA[A]PP\tnext\n");
1128 if(!FLAC__metadata_simple_iterator_next(iterator))
1129 return die_("iterator ended early\n");
1130 our_current_position++;
1132 printf("SVAA[P]P\tnext\n");
1133 if(!FLAC__metadata_simple_iterator_next(iterator))
1134 return die_("iterator ended early\n");
1135 our_current_position++;
1137 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1138 padding->length = 5;
1139 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1140 return die_("copying object");
1141 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1142 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1144 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1147 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1148 app->data.application.id[0] = 'k'; /* twiddle the id */
1149 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1150 return die_("copying object");
1151 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1152 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1154 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1157 printf("SVAAP[A]\tset PADDING (equal)\n");
1158 padding->length = 27;
1159 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1160 return die_("copying object");
1161 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1162 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1164 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1167 printf("SVAAP[P]\tprev\n");
1168 if(!FLAC__metadata_simple_iterator_prev(iterator))
1169 return die_("iterator ended early\n");
1170 our_current_position--;
1172 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1173 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1174 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1175 delete_from_our_metadata_(our_current_position--);
1177 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1180 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1181 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1182 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1183 delete_from_our_metadata_(our_current_position--);
1185 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1188 printf("SV[A]P\tnext\n");
1189 if(!FLAC__metadata_simple_iterator_next(iterator))
1190 return die_("iterator ended early\n");
1191 our_current_position++;
1193 printf("SVA[P]\tinsert PADDING after\n");
1194 padding->length = 5;
1195 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1196 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1197 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1200 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1203 printf("SVAP[P]\tprev\n");
1204 if(!FLAC__metadata_simple_iterator_prev(iterator))
1205 return die_("iterator ended early\n");
1206 our_current_position--;
1208 printf("SVA[P]P\tprev\n");
1209 if(!FLAC__metadata_simple_iterator_prev(iterator))
1210 return die_("iterator ended early\n");
1211 our_current_position--;
1213 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1214 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1215 return die_("setting APPLICATION data");
1216 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1217 return die_("copying object");
1218 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1219 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1221 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1224 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1225 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1226 return die_("setting APPLICATION data");
1227 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1228 return die_("copying object");
1229 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1230 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1232 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1235 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1236 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1237 return die_("setting APPLICATION data");
1238 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1239 return die_("copying object");
1240 our_metadata_.blocks[our_current_position+1]->length = 0;
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_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1247 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1248 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1249 return die_("setting APPLICATION data");
1250 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1251 return die_("copying object");
1252 delete_from_our_metadata_(our_current_position+1);
1253 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1254 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1256 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1259 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1260 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1261 return die_("setting APPLICATION data");
1262 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1263 return die_("copying object");
1264 delete_from_our_metadata_(our_current_position+1);
1265 our_metadata_.blocks[our_current_position]->is_last = true;
1266 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1267 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1269 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1272 printf("SV[A]\tset PADDING (equal size)\n");
1273 padding->length = app->length;
1274 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1275 return die_("copying object");
1276 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1277 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1279 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1282 printf("SV[P]\tinsert PADDING after\n");
1283 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1284 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1285 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1288 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1291 printf("SVP[P]\tinsert PADDING after\n");
1292 padding->length = 5;
1293 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1294 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1295 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1298 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1301 printf("SVPP[P]\tprev\n");
1302 if(!FLAC__metadata_simple_iterator_prev(iterator))
1303 return die_("iterator ended early\n");
1304 our_current_position--;
1306 printf("SVP[P]P\tprev\n");
1307 if(!FLAC__metadata_simple_iterator_prev(iterator))
1308 return die_("iterator ended early\n");
1309 our_current_position--;
1311 printf("SV[P]PP\tprev\n");
1312 if(!FLAC__metadata_simple_iterator_prev(iterator))
1313 return die_("iterator ended early\n");
1314 our_current_position--;
1316 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1317 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1318 return die_("setting APPLICATION data");
1319 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1320 return die_("copying object");
1321 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1322 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1324 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1327 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1328 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1329 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1330 delete_from_our_metadata_(our_current_position--);
1332 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1335 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1336 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1337 return die_("setting APPLICATION data");
1338 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1339 return die_("copying object");
1340 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1341 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1343 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1346 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1347 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1348 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1349 delete_from_our_metadata_(our_current_position--);
1351 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1354 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1355 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1356 return die_("setting APPLICATION data");
1357 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1358 return die_("copying object");
1359 delete_from_our_metadata_(our_current_position+1);
1360 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1361 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1363 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1366 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1367 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1368 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1369 delete_from_our_metadata_(our_current_position--);
1371 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1374 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1375 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1376 return die_("setting APPLICATION data");
1377 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1378 return die_("copying object");
1379 our_metadata_.blocks[our_current_position+1]->length = 0;
1380 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1381 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1383 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1386 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1387 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1388 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1389 delete_from_our_metadata_(our_current_position--);
1391 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1394 printf("S[V]PP\tnext\n");
1395 if(!FLAC__metadata_simple_iterator_next(iterator))
1396 return die_("iterator ended early\n");
1397 our_current_position++;
1399 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1400 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1401 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1402 delete_from_our_metadata_(our_current_position--);
1404 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1407 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1408 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1409 return die_("setting APPLICATION data");
1410 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1411 return die_("copying object");
1412 delete_from_our_metadata_(our_current_position+1);
1413 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1414 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1416 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1419 printf("delete simple iterator\n");
1421 FLAC__metadata_simple_iterator_delete(iterator);
1423 FLAC__metadata_object_delete(app);
1424 FLAC__metadata_object_delete(padding);
1426 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1432 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1434 FLAC__Metadata_Iterator *iterator;
1435 FLAC__Metadata_Chain *chain;
1436 FLAC__StreamMetadata *block, *app, *padding;
1437 FLAC__byte data[2000];
1438 unsigned our_current_position;
1440 /* initialize 'data' to avoid Valgrind errors */
1441 memset(data, 0, sizeof(data));
1443 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1445 printf("generate read-only file\n");
1447 if(!generate_file_(/*include_extras=*/false, is_ogg))
1450 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1453 printf("create chain\n");
1455 if(0 == (chain = FLAC__metadata_chain_new()))
1456 return die_("allocating chain");
1458 printf("read chain\n");
1460 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1461 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1463 printf("[S]VP\ttest initial metadata\n");
1465 if(!compare_chain_(chain, 0, 0))
1467 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1473 printf("switch file to read-write\n");
1475 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1478 printf("create iterator\n");
1479 if(0 == (iterator = FLAC__metadata_iterator_new()))
1480 return die_("allocating memory for iterator");
1482 our_current_position = 0;
1484 FLAC__metadata_iterator_init(iterator, chain);
1486 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1487 return die_("getting block from iterator");
1489 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1491 printf("[S]VP\tmodify STREAMINFO, write\n");
1493 block->data.stream_info.sample_rate = 32000;
1494 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1495 return die_("copying object");
1497 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1498 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1499 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1501 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1504 printf("[S]VP\tnext\n");
1505 if(!FLAC__metadata_iterator_next(iterator))
1506 return die_("iterator ended early\n");
1507 our_current_position++;
1509 printf("S[V]P\tnext\n");
1510 if(!FLAC__metadata_iterator_next(iterator))
1511 return die_("iterator ended early\n");
1512 our_current_position++;
1514 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1515 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1516 return die_("getting block from iterator");
1517 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1518 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1519 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1520 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1521 return die_("setting APPLICATION data");
1522 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1523 return die_("copying object");
1524 if(!FLAC__metadata_iterator_set_block(iterator, app))
1525 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1527 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1528 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1529 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1531 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1534 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1535 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1536 return die_("copying object");
1537 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1538 return die_("setting APPLICATION data");
1539 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1540 return die_("copying object");
1541 if(!FLAC__metadata_iterator_set_block(iterator, app))
1542 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1544 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1545 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1546 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1548 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1551 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1552 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1553 return die_("copying object");
1554 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1555 return die_("setting APPLICATION data");
1556 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1557 return die_("copying object");
1558 if(!FLAC__metadata_iterator_set_block(iterator, app))
1559 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1561 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1562 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1563 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1565 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1568 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1569 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1570 return die_("copying object");
1571 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1572 return die_("setting APPLICATION data");
1573 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1574 return die_("copying object");
1575 if(!FLAC__metadata_iterator_set_block(iterator, app))
1576 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1578 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1579 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1580 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1582 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1585 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1586 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1587 return die_("copying object");
1588 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1589 return die_("setting APPLICATION data");
1590 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1591 return die_("copying object");
1592 if(!FLAC__metadata_iterator_set_block(iterator, app))
1593 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1595 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1596 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1597 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1599 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1602 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1603 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1604 return die_("creating PADDING block");
1605 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1606 return die_("copying object");
1607 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1608 return die_("setting APPLICATION data");
1609 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1610 return die_("copying object");
1611 padding->length = 0;
1612 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1613 return die_("internal error");
1614 if(!FLAC__metadata_iterator_set_block(iterator, app))
1615 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1617 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1618 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1619 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1621 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1624 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1625 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1626 return die_("copying object");
1627 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1628 return die_("setting APPLICATION data");
1629 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1630 return die_("copying object");
1631 our_metadata_.blocks[our_current_position+1]->length = 13;
1632 if(!FLAC__metadata_iterator_set_block(iterator, app))
1633 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1635 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1636 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1637 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1639 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1642 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1643 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1644 return die_("copying object");
1645 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1646 return die_("setting APPLICATION data");
1647 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1648 return die_("copying object");
1649 if(!FLAC__metadata_iterator_set_block(iterator, app))
1650 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1652 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1653 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1654 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1656 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1659 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1660 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1661 return die_("copying object");
1662 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1663 return die_("setting APPLICATION data");
1664 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1665 return die_("copying object");
1666 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1667 if(!FLAC__metadata_iterator_set_block(iterator, app))
1668 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1670 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1671 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1672 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1674 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1677 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1678 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1679 return die_("copying object");
1680 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1681 return die_("setting APPLICATION data");
1682 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1683 return die_("copying object");
1684 delete_from_our_metadata_(our_current_position+1);
1685 if(!FLAC__metadata_iterator_set_block(iterator, app))
1686 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1688 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1689 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1690 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1692 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1695 printf("SV[A]\tprev\n");
1696 if(!FLAC__metadata_iterator_prev(iterator))
1697 return die_("iterator ended early\n");
1698 our_current_position--;
1700 printf("S[V]A\tprev\n");
1701 if(!FLAC__metadata_iterator_prev(iterator))
1702 return die_("iterator ended early\n");
1703 our_current_position--;
1705 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1706 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1707 return die_("creating PADDING block");
1708 padding->length = 30;
1709 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1710 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1712 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1714 printf("[S]VP\tnext\n");
1715 if(!FLAC__metadata_iterator_next(iterator))
1716 return die_("iterator ended early\n");
1717 our_current_position++;
1719 printf("S[V]A\tinsert PADDING after\n");
1720 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1721 return die_("copying metadata");
1722 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1723 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1725 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1728 printf("SV[P]A\tinsert PADDING before\n");
1729 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1730 return die_("creating PADDING block");
1731 padding->length = 17;
1732 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1733 return die_("copying metadata");
1734 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1735 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1737 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1740 printf("SV[P]PA\tinsert PADDING before\n");
1741 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1742 return die_("creating PADDING block");
1743 padding->length = 0;
1744 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1745 return die_("copying metadata");
1746 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1747 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1749 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1752 printf("SV[P]PPA\tnext\n");
1753 if(!FLAC__metadata_iterator_next(iterator))
1754 return die_("iterator ended early\n");
1755 our_current_position++;
1757 printf("SVP[P]PA\tnext\n");
1758 if(!FLAC__metadata_iterator_next(iterator))
1759 return die_("iterator ended early\n");
1760 our_current_position++;
1762 printf("SVPP[P]A\tnext\n");
1763 if(!FLAC__metadata_iterator_next(iterator))
1764 return die_("iterator ended early\n");
1765 our_current_position++;
1767 printf("SVPPP[A]\tinsert PADDING after\n");
1768 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1769 return die_("creating PADDING block");
1770 padding->length = 57;
1771 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1772 return die_("copying metadata");
1773 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1774 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1776 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1779 printf("SVPPPA[P]\tinsert PADDING before\n");
1780 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1781 return die_("creating PADDING block");
1782 padding->length = 99;
1783 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1784 return die_("copying metadata");
1785 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1786 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1788 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1791 printf("delete iterator\n");
1792 FLAC__metadata_iterator_delete(iterator);
1793 our_current_position = 0;
1795 printf("SVPPPAPP\tmerge padding\n");
1796 FLAC__metadata_chain_merge_padding(chain);
1797 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1798 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1799 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1800 delete_from_our_metadata_(7);
1801 delete_from_our_metadata_(4);
1802 delete_from_our_metadata_(3);
1804 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1805 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1806 if(!compare_chain_(chain, 0, 0))
1808 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1811 printf("SVPAP\tsort padding\n");
1812 FLAC__metadata_chain_sort_padding(chain);
1813 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1814 delete_from_our_metadata_(2);
1816 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1817 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1818 if(!compare_chain_(chain, 0, 0))
1820 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1823 printf("create iterator\n");
1824 if(0 == (iterator = FLAC__metadata_iterator_new()))
1825 return die_("allocating memory for iterator");
1827 our_current_position = 0;
1829 FLAC__metadata_iterator_init(iterator, chain);
1831 printf("[S]VAP\tnext\n");
1832 if(!FLAC__metadata_iterator_next(iterator))
1833 return die_("iterator ended early\n");
1834 our_current_position++;
1836 printf("S[V]AP\tnext\n");
1837 if(!FLAC__metadata_iterator_next(iterator))
1838 return die_("iterator ended early\n");
1839 our_current_position++;
1841 printf("SV[A]P\tdelete middle block, replace with padding\n");
1842 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1843 return die_("creating PADDING block");
1844 padding->length = 71;
1845 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1846 return die_("copying object");
1847 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1848 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1850 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1853 printf("S[V]PP\tnext\n");
1854 if(!FLAC__metadata_iterator_next(iterator))
1855 return die_("iterator ended early\n");
1856 our_current_position++;
1858 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1859 delete_from_our_metadata_(our_current_position--);
1860 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1861 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1863 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1866 printf("S[V]P\tnext\n");
1867 if(!FLAC__metadata_iterator_next(iterator))
1868 return die_("iterator ended early\n");
1869 our_current_position++;
1871 printf("SV[P]\tdelete last block, replace with padding\n");
1872 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1873 return die_("creating PADDING block");
1874 padding->length = 219;
1875 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1876 return die_("copying object");
1877 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1878 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1880 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1883 printf("S[V]P\tnext\n");
1884 if(!FLAC__metadata_iterator_next(iterator))
1885 return die_("iterator ended early\n");
1886 our_current_position++;
1888 printf("SV[P]\tdelete last block, don't replace with padding\n");
1889 delete_from_our_metadata_(our_current_position--);
1890 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1891 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1893 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1896 printf("S[V]\tprev\n");
1897 if(!FLAC__metadata_iterator_prev(iterator))
1898 return die_("iterator ended early\n");
1899 our_current_position--;
1901 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1902 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1903 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1905 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1908 printf("delete iterator\n");
1909 FLAC__metadata_iterator_delete(iterator);
1910 our_current_position = 0;
1912 printf("SV\tmerge padding\n");
1913 FLAC__metadata_chain_merge_padding(chain);
1915 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1916 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1917 if(!compare_chain_(chain, 0, 0))
1919 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1922 printf("SV\tsort padding\n");
1923 FLAC__metadata_chain_sort_padding(chain);
1925 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1926 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1927 if(!compare_chain_(chain, 0, 0))
1929 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1933 printf("delete chain\n");
1935 FLAC__metadata_chain_delete(chain);
1937 if(!remove_file_(flacfilename(is_ogg)))
1943 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1945 FLAC__Metadata_Iterator *iterator;
1946 FLAC__Metadata_Chain *chain;
1947 FLAC__IOCallbacks callbacks;
1949 memset(&callbacks, 0, sizeof(callbacks));
1950 callbacks.read = (FLAC__IOCallback_Read)fread;
1951 #ifdef FLAC__VALGRIND_TESTING
1952 callbacks.write = chain_write_cb_;
1954 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1956 callbacks.seek = chain_seek_cb_;
1957 callbacks.tell = chain_tell_cb_;
1958 callbacks.eof = chain_eof_cb_;
1960 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1962 printf("generate file\n");
1964 if(!generate_file_(/*include_extras=*/false, is_ogg))
1967 printf("create chain\n");
1969 if(0 == (chain = FLAC__metadata_chain_new()))
1970 return die_("allocating chain");
1972 printf("read chain (filename-based)\n");
1974 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1975 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1977 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1979 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1980 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1981 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1982 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1983 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1986 printf("read chain (filename-based)\n");
1988 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1989 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1991 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1993 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1994 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1995 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1996 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1997 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2000 printf("read chain (callback-based)\n");
2002 FILE *file = fopen(flacfilename(is_ogg), "rb");
2004 return die_("opening file");
2005 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2007 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2012 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2014 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2015 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2016 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2017 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2018 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2021 printf("read chain (callback-based)\n");
2023 FILE *file = fopen(flacfilename(is_ogg), "rb");
2025 return die_("opening file");
2026 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2028 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2033 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2035 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2036 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2038 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2040 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2042 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2043 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2044 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2045 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2046 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2049 printf("read chain (callback-based)\n");
2051 FILE *file = fopen(flacfilename(is_ogg), "rb");
2053 return die_("opening file");
2054 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2056 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2061 printf("create iterator\n");
2062 if(0 == (iterator = FLAC__metadata_iterator_new()))
2063 return die_("allocating memory for iterator");
2065 FLAC__metadata_iterator_init(iterator, chain);
2067 printf("[S]VP\tnext\n");
2068 if(!FLAC__metadata_iterator_next(iterator))
2069 return die_("iterator ended early\n");
2071 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2072 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2073 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2075 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2077 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2078 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2080 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2082 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2084 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2085 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2086 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2087 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2088 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2091 printf("delete iterator\n");
2093 FLAC__metadata_iterator_delete(iterator);
2095 printf("delete chain\n");
2097 FLAC__metadata_chain_delete(chain);
2099 if(!remove_file_(flacfilename(is_ogg)))
2105 FLAC__bool test_metadata_file_manipulation(void)
2107 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2109 our_metadata_.num_blocks = 0;
2111 if(!test_level_0_())
2114 if(!test_level_1_())
2117 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2119 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2121 if(!test_level_2_misc_(/*is_ogg=*/false))
2124 if(FLAC_API_SUPPORTS_OGG_FLAC) {
2125 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2127 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2130 /* when ogg flac write is supported, will have to add this: */
2131 if(!test_level_2_misc_(/*is_ogg=*/true))