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 /* our copy of the metadata in flacfilename() */
67 static our_metadata_struct our_metadata_;
69 /* the current block number that corresponds to the position of the iterator we are testing */
70 static unsigned mc_our_block_number_ = 0;
72 static const char *flacfilename(FLAC__bool is_ogg)
74 return is_ogg? "metadata.ogg" : "metadata.flac";
77 static FLAC__bool die_(const char *msg)
79 printf("ERROR: %s\n", msg);
83 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
85 printf("ERROR: %s\n", msg);
86 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
90 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
92 printf("ERROR: %s\n", msg);
93 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
97 static void *malloc_or_die_(size_t size)
99 void *x = malloc(size);
101 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
107 static char *strdup_or_die_(const char *s)
111 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
117 /* functions for working with our metadata copy */
119 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
122 FLAC__StreamMetadata *obj = block;
123 FLAC__ASSERT(position < our_metadata_.num_blocks);
125 if(0 == (obj = FLAC__metadata_object_clone(block)))
126 return die_("during FLAC__metadata_object_clone()");
128 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
129 our_metadata_.blocks[position] = obj;
131 /* set the is_last flags */
132 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
133 our_metadata_.blocks[i]->is_last = false;
134 our_metadata_.blocks[i]->is_last = true;
139 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
142 FLAC__StreamMetadata *obj = block;
144 if(0 == (obj = FLAC__metadata_object_clone(block)))
145 return die_("during FLAC__metadata_object_clone()");
147 if(position > our_metadata_.num_blocks) {
148 position = our_metadata_.num_blocks;
151 for(i = our_metadata_.num_blocks; i > position; i--)
152 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
154 our_metadata_.blocks[position] = obj;
155 our_metadata_.num_blocks++;
157 /* set the is_last flags */
158 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
159 our_metadata_.blocks[i]->is_last = false;
160 our_metadata_.blocks[i]->is_last = true;
165 static void delete_from_our_metadata_(unsigned position)
168 FLAC__ASSERT(position < our_metadata_.num_blocks);
169 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
170 for(i = position; i < our_metadata_.num_blocks - 1; i++)
171 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
172 our_metadata_.num_blocks--;
174 /* set the is_last flags */
175 if(our_metadata_.num_blocks > 0) {
176 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
177 our_metadata_.blocks[i]->is_last = false;
178 our_metadata_.blocks[i]->is_last = true;
183 * This wad of functions supports filename- and callback-based chain reading/writing.
184 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
186 FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
188 static const char *tempfile_suffix = ".metadata_edit";
190 if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
192 strcpy(*tempfilename, filename);
193 strcat(*tempfilename, tempfile_suffix);
195 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
201 void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
204 (void)fclose(*tempfile);
208 if(0 != *tempfilename) {
209 (void)unlink(*tempfilename);
215 FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
217 FLAC__ASSERT(0 != filename);
218 FLAC__ASSERT(0 != tempfile);
219 FLAC__ASSERT(0 != tempfilename);
220 FLAC__ASSERT(0 != *tempfilename);
223 (void)fclose(*tempfile);
227 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
228 /* on some flavors of windows, rename() will fail if the destination already exists */
229 if(unlink(filename) < 0) {
230 cleanup_tempfile_(tempfile, tempfilename);
235 if(0 != rename(*tempfilename, filename)) {
236 cleanup_tempfile_(tempfile, tempfilename);
240 cleanup_tempfile_(tempfile, tempfilename);
245 FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
247 FLAC__ASSERT(0 != filename);
248 FLAC__ASSERT(0 != stats);
249 return (0 == stat(filename, stats));
252 void set_file_stats_(const char *filename, struct stat *stats)
254 struct utimbuf srctime;
256 FLAC__ASSERT(0 != filename);
257 FLAC__ASSERT(0 != stats);
259 srctime.actime = stats->st_atime;
260 srctime.modtime = stats->st_mtime;
261 (void)chmod(filename, stats->st_mode);
262 (void)utime(filename, &srctime);
263 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
264 (void)chown(filename, stats->st_uid, -1);
265 (void)chown(filename, -1, stats->st_gid);
269 #ifdef FLAC__VALGRIND_TESTING
270 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
272 FILE *stream = (FILE*)handle;
273 size_t ret = fwrite(ptr, size, nmemb, stream);
280 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
282 off_t o = (off_t)offset;
283 FLAC__ASSERT(offset == o);
284 return fseeko((FILE*)handle, o, whence);
287 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
289 return ftello((FILE*)handle);
292 static int chain_eof_cb_(FLAC__IOHandle handle)
294 return feof((FILE*)handle);
297 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)
300 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
302 FLAC__IOCallbacks callbacks;
304 memset(&callbacks, 0, sizeof(callbacks));
305 callbacks.read = (FLAC__IOCallback_Read)fread;
306 #ifdef FLAC__VALGRIND_TESTING
307 callbacks.write = chain_write_cb_;
309 callbacks.write = (FLAC__IOCallback_Write)fwrite;
311 callbacks.seek = chain_seek_cb_;
312 callbacks.eof = chain_eof_cb_;
314 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
316 FILE *file, *tempfile;
318 if(preserve_file_stats) {
319 if(!get_file_stats_(filename, &stats))
322 if(0 == (file = fopen(filename, "rb")))
323 return false; /*@@@@ chain status still says OK though */
324 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
326 cleanup_tempfile_(&tempfile, &tempfilename);
327 return false; /*@@@@ chain status still says OK though */
329 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
337 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
339 if(preserve_file_stats)
340 set_file_stats_(filename, &stats);
343 FILE *file = fopen(filename, "r+b");
345 return false; /*@@@@ chain status still says OK though */
346 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
355 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based, FLAC__bool is_ogg)
359 FLAC__metadata_chain_read_ogg(chain, flacfilename(is_ogg)) :
360 FLAC__metadata_chain_read(chain, flacfilename(is_ogg))
363 FLAC__IOCallbacks callbacks;
365 memset(&callbacks, 0, sizeof(callbacks));
366 callbacks.read = (FLAC__IOCallback_Read)fread;
367 callbacks.seek = chain_seek_cb_;
368 callbacks.tell = chain_tell_cb_;
372 FILE *file = fopen(filename, "rb");
374 return false; /*@@@@ chain status still says OK though */
376 FLAC__metadata_chain_read_ogg_with_callbacks(chain, (FLAC__IOHandle)file, callbacks) :
377 FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)
385 /* function for comparing our metadata to a FLAC__Metadata_Chain */
387 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
390 FLAC__Metadata_Iterator *iterator;
391 FLAC__StreamMetadata *block;
392 FLAC__bool next_ok = true;
394 FLAC__ASSERT(0 != chain);
396 printf("\tcomparing chain... ");
399 if(0 == (iterator = FLAC__metadata_iterator_new()))
400 return die_("allocating memory for iterator");
402 FLAC__metadata_iterator_init(iterator, chain);
409 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
410 FLAC__metadata_iterator_delete(iterator);
411 return die_("getting block from iterator");
414 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
415 FLAC__metadata_iterator_delete(iterator);
416 return die_("metadata block mismatch");
420 next_ok = FLAC__metadata_iterator_next(iterator);
421 } while(i < our_metadata_.num_blocks && next_ok);
423 FLAC__metadata_iterator_delete(iterator);
426 return die_("chain has more blocks than expected");
428 if(i < our_metadata_.num_blocks)
429 return die_("short block count in chain");
431 if(0 != current_block) {
432 printf("CURRENT_POSITION... ");
435 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
436 return die_("metadata block mismatch");
444 /* decoder callbacks for checking the file */
446 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
448 (void)decoder, (void)buffer, (void)client_data;
451 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
452 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
454 printf("content... ");
458 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
461 /* this version pays no attention to the metadata */
462 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
464 (void)decoder, (void)metadata, (void)client_data;
466 printf("%d... ", mc_our_block_number_);
469 mc_our_block_number_++;
472 /* this version is used when we want to compare to our metadata copy */
473 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
475 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
479 /* don't bother checking if we've already hit an error */
480 if(dcd->error_occurred)
483 printf("%d... ", mc_our_block_number_);
486 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
487 (void)die_("got more metadata blocks than expected");
488 dcd->error_occurred = true;
491 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
492 (void)die_("metadata block mismatch");
493 dcd->error_occurred = true;
496 mc_our_block_number_++;
499 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
501 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
504 dcd->error_occurred = true;
505 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
508 static FLAC__bool generate_file_(FLAC__bool include_extras, FLAC__bool is_ogg)
510 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
511 FLAC__StreamMetadata *metadata[4];
512 unsigned i = 0, n = 0;
514 printf("generating %sFLAC file for test\n", is_ogg? "Ogg " : "");
516 while(our_metadata_.num_blocks > 0)
517 delete_from_our_metadata_(0);
519 streaminfo.is_last = false;
520 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
521 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
522 streaminfo.data.stream_info.min_blocksize = 576;
523 streaminfo.data.stream_info.max_blocksize = 576;
524 streaminfo.data.stream_info.min_framesize = 0;
525 streaminfo.data.stream_info.max_framesize = 0;
526 streaminfo.data.stream_info.sample_rate = 44100;
527 streaminfo.data.stream_info.channels = 1;
528 streaminfo.data.stream_info.bits_per_sample = 8;
529 streaminfo.data.stream_info.total_samples = 0;
530 memset(streaminfo.data.stream_info.md5sum, 0, 16);
533 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
534 vorbiscomment.is_last = false;
535 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
536 vorbiscomment.length = (4 + vendor_string_length) + 4;
537 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
538 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
539 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
540 vorbiscomment.data.vorbis_comment.num_comments = 0;
541 vorbiscomment.data.vorbis_comment.comments = 0;
545 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
546 return die_("priming our metadata");
547 cuesheet->is_last = false;
548 strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
549 cuesheet->data.cue_sheet.lead_in = 123;
550 cuesheet->data.cue_sheet.is_cd = false;
551 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
552 return die_("priming our metadata");
553 cuesheet->data.cue_sheet.tracks[0].number = 1;
554 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
555 return die_("priming our metadata");
559 picture.is_last = false;
560 picture.type = FLAC__METADATA_TYPE_PICTURE;
563 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
564 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
565 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
566 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
567 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
568 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
569 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
570 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
573 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
574 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
575 picture.length += strlen(picture.data.picture.mime_type);
576 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
577 picture.length += strlen((const char *)picture.data.picture.description);
578 picture.data.picture.width = 300;
579 picture.data.picture.height = 300;
580 picture.data.picture.depth = 24;
581 picture.data.picture.colors = 0;
582 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
583 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
584 picture.length += picture.data.picture.data_length;
587 padding.is_last = true;
588 padding.type = FLAC__METADATA_TYPE_PADDING;
589 padding.length = 1234;
591 metadata[n++] = &vorbiscomment;
593 metadata[n++] = cuesheet;
594 metadata[n++] = &picture;
596 metadata[n++] = &padding;
599 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
600 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
601 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
602 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
603 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
605 return die_("priming our metadata");
607 if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), 0, 512 * 1024, &streaminfo, metadata, n))
608 return die_("creating the encoded file");
610 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
615 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
617 const char *filename = flacfilename(is_ogg);
618 FLAC__StreamDecoder *decoder;
619 decoder_client_struct decoder_client_data;
621 FLAC__ASSERT(0 != metadata_callback);
623 mc_our_block_number_ = 0;
624 decoder_client_data.error_occurred = false;
626 printf("\ttesting '%s'... ", filename);
629 if(0 == (decoder = FLAC__stream_decoder_new()))
630 return die_("couldn't allocate decoder instance");
632 FLAC__stream_decoder_set_md5_checking(decoder, true);
633 FLAC__stream_decoder_set_metadata_respond_all(decoder);
636 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
637 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
638 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
640 (void)FLAC__stream_decoder_finish(decoder);
641 FLAC__stream_decoder_delete(decoder);
642 return die_("initializing decoder\n");
644 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
645 (void)FLAC__stream_decoder_finish(decoder);
646 FLAC__stream_decoder_delete(decoder);
647 return die_("decoding file\n");
650 (void)FLAC__stream_decoder_finish(decoder);
651 FLAC__stream_decoder_delete(decoder);
653 if(decoder_client_data.error_occurred)
656 if(mc_our_block_number_ != our_metadata_.num_blocks)
657 return die_("short metadata block count");
663 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
665 if(!grabbag__file_change_stats(filename, read_only))
666 return die_("during grabbag__file_change_stats()");
671 static FLAC__bool remove_file_(const char *filename)
673 while(our_metadata_.num_blocks > 0)
674 delete_from_our_metadata_(0);
676 if(!grabbag__file_remove_file(filename))
677 return die_("removing file");
682 static FLAC__bool test_level_0_()
684 FLAC__StreamMetadata streaminfo;
685 FLAC__StreamMetadata *tags = 0;
686 FLAC__StreamMetadata *cuesheet = 0;
687 FLAC__StreamMetadata *picture = 0;
689 printf("\n\n++++++ testing level 0 interface\n");
691 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
694 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
697 printf("testing FLAC__metadata_get_streaminfo()... ");
699 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
700 return die_("during FLAC__metadata_get_streaminfo()");
702 /* check to see if some basic data matches (c.f. generate_file_()) */
703 if(streaminfo.data.stream_info.channels != 1)
704 return die_("mismatch in streaminfo.data.stream_info.channels");
705 if(streaminfo.data.stream_info.bits_per_sample != 8)
706 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
707 if(streaminfo.data.stream_info.sample_rate != 44100)
708 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
709 if(streaminfo.data.stream_info.min_blocksize != 576)
710 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
711 if(streaminfo.data.stream_info.max_blocksize != 576)
712 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
716 printf("testing FLAC__metadata_get_tags()... ");
718 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
719 return die_("during FLAC__metadata_get_tags()");
721 /* check to see if some basic data matches (c.f. generate_file_()) */
722 if(tags->data.vorbis_comment.num_comments != 0)
723 return die_("mismatch in tags->data.vorbis_comment.num_comments");
727 FLAC__metadata_object_delete(tags);
729 printf("testing FLAC__metadata_get_cuesheet()... ");
731 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
732 return die_("during FLAC__metadata_get_cuesheet()");
734 /* check to see if some basic data matches (c.f. generate_file_()) */
735 if(cuesheet->data.cue_sheet.lead_in != 123)
736 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
740 FLAC__metadata_object_delete(cuesheet);
742 printf("testing FLAC__metadata_get_picture()... ");
744 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)))
745 return die_("during FLAC__metadata_get_picture()");
747 /* check to see if some basic data matches (c.f. generate_file_()) */
748 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
749 return die_("mismatch in picture->data.picture.type");
753 FLAC__metadata_object_delete(picture);
755 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
761 static FLAC__bool test_level_1_()
763 FLAC__Metadata_SimpleIterator *iterator;
764 FLAC__StreamMetadata *block, *app, *padding;
765 FLAC__byte data[1000];
766 unsigned our_current_position = 0;
768 /* initialize 'data' to avoid Valgrind errors */
769 memset(data, 0, sizeof(data));
771 printf("\n\n++++++ testing level 1 interface\n");
773 /************************************************************/
775 printf("simple iterator on read-only file\n");
777 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
780 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
783 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
786 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
787 return die_("FLAC__metadata_simple_iterator_new()");
789 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
790 return die_("FLAC__metadata_simple_iterator_init() returned false");
792 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
793 if(FLAC__metadata_simple_iterator_is_writable(iterator))
794 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
796 printf("iterate forwards\n");
798 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
799 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
800 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
801 return die_("getting block 0");
802 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
803 return die_("expected STREAMINFO type");
805 return die_("expected is_last to be false");
806 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
807 return die_("bad STREAMINFO length");
808 /* check to see if some basic data matches (c.f. generate_file_()) */
809 if(block->data.stream_info.channels != 1)
810 return die_("mismatch in channels");
811 if(block->data.stream_info.bits_per_sample != 8)
812 return die_("mismatch in bits_per_sample");
813 if(block->data.stream_info.sample_rate != 44100)
814 return die_("mismatch in sample_rate");
815 if(block->data.stream_info.min_blocksize != 576)
816 return die_("mismatch in min_blocksize");
817 if(block->data.stream_info.max_blocksize != 576)
818 return die_("mismatch in max_blocksize");
819 FLAC__metadata_object_delete(block);
821 if(!FLAC__metadata_simple_iterator_next(iterator))
822 return die_("forward iterator ended early");
823 our_current_position++;
825 if(!FLAC__metadata_simple_iterator_next(iterator))
826 return die_("forward iterator ended early");
827 our_current_position++;
829 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
830 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
831 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
832 return die_("getting block 2");
833 if(block->type != FLAC__METADATA_TYPE_PADDING)
834 return die_("expected PADDING type");
836 return die_("expected is_last to be true");
837 /* check to see if some basic data matches (c.f. generate_file_()) */
838 if(block->length != 1234)
839 return die_("bad PADDING length");
840 FLAC__metadata_object_delete(block);
842 if(FLAC__metadata_simple_iterator_next(iterator))
843 return die_("forward iterator returned true but should have returned false");
845 printf("iterate backwards\n");
846 if(!FLAC__metadata_simple_iterator_prev(iterator))
847 return die_("reverse iterator ended early");
848 if(!FLAC__metadata_simple_iterator_prev(iterator))
849 return die_("reverse iterator ended early");
850 if(FLAC__metadata_simple_iterator_prev(iterator))
851 return die_("reverse iterator returned true but should have returned false");
853 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
855 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
856 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
858 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
860 FLAC__metadata_simple_iterator_delete(iterator);
862 /************************************************************/
864 printf("simple iterator on writable file\n");
866 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
869 printf("creating APPLICATION block\n");
871 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
872 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
873 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
875 printf("creating PADDING block\n");
877 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
878 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
879 padding->length = 20;
881 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
882 return die_("FLAC__metadata_simple_iterator_new()");
884 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
885 return die_("FLAC__metadata_simple_iterator_init() returned false");
886 our_current_position = 0;
888 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
890 printf("[S]VP\ttry to write over STREAMINFO block...\n");
891 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
892 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
894 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
896 printf("[S]VP\tnext\n");
897 if(!FLAC__metadata_simple_iterator_next(iterator))
898 return die_("iterator ended early\n");
899 our_current_position++;
901 printf("S[V]P\tnext\n");
902 if(!FLAC__metadata_simple_iterator_next(iterator))
903 return die_("iterator ended early\n");
904 our_current_position++;
906 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
907 padding->length = 25;
908 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
909 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
910 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
913 printf("SVP[P]\tprev\n");
914 if(!FLAC__metadata_simple_iterator_prev(iterator))
915 return die_("iterator ended early\n");
916 our_current_position--;
918 printf("SV[P]P\tprev\n");
919 if(!FLAC__metadata_simple_iterator_prev(iterator))
920 return die_("iterator ended early\n");
921 our_current_position--;
923 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
924 padding->length = 30;
925 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
926 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
927 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
930 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
933 printf("SV[P]PP\tprev\n");
934 if(!FLAC__metadata_simple_iterator_prev(iterator))
935 return die_("iterator ended early\n");
936 our_current_position--;
938 printf("S[V]PPP\tprev\n");
939 if(!FLAC__metadata_simple_iterator_prev(iterator))
940 return die_("iterator ended early\n");
941 our_current_position--;
943 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
944 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
945 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
947 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
950 printf("[S]VPPP\tnext\n");
951 if(!FLAC__metadata_simple_iterator_next(iterator))
952 return die_("iterator ended early\n");
953 our_current_position++;
955 printf("S[V]PPP\tnext\n");
956 if(!FLAC__metadata_simple_iterator_next(iterator))
957 return die_("iterator ended early\n");
958 our_current_position++;
960 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
961 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
962 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
963 our_current_position--;
965 printf("S[V]PPP\tnext\n");
966 if(!FLAC__metadata_simple_iterator_next(iterator))
967 return die_("iterator ended early\n");
968 our_current_position++;
970 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
971 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
972 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
973 delete_from_our_metadata_(our_current_position--);
975 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
978 printf("S[V]PP\tnext\n");
979 if(!FLAC__metadata_simple_iterator_next(iterator))
980 return die_("iterator ended early\n");
981 our_current_position++;
983 printf("SV[P]P\tnext\n");
984 if(!FLAC__metadata_simple_iterator_next(iterator))
985 return die_("iterator ended early\n");
986 our_current_position++;
988 printf("SVP[P]\tdelete (last block), replace with padding\n");
989 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
990 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
991 our_current_position--;
993 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
996 printf("SV[P]P\tnext\n");
997 if(!FLAC__metadata_simple_iterator_next(iterator))
998 return die_("iterator ended early\n");
999 our_current_position++;
1001 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1002 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1003 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1004 delete_from_our_metadata_(our_current_position--);
1006 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1009 printf("SV[P]\tprev\n");
1010 if(!FLAC__metadata_simple_iterator_prev(iterator))
1011 return die_("iterator ended early\n");
1012 our_current_position--;
1014 printf("S[V]P\tprev\n");
1015 if(!FLAC__metadata_simple_iterator_prev(iterator))
1016 return die_("iterator ended early\n");
1017 our_current_position--;
1019 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1020 FLAC__ASSERT(our_current_position == 0);
1021 block = FLAC__metadata_simple_iterator_get_block(iterator);
1022 block->data.stream_info.sample_rate = 32000;
1023 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1024 return die_("copying object");
1025 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1026 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1027 FLAC__metadata_object_delete(block);
1029 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1032 printf("[S]VP\tnext\n");
1033 if(!FLAC__metadata_simple_iterator_next(iterator))
1034 return die_("iterator ended early\n");
1035 our_current_position++;
1037 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1038 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1039 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1040 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1041 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1043 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1045 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1048 printf("SV[A]P\tnext\n");
1049 if(!FLAC__metadata_simple_iterator_next(iterator))
1050 return die_("iterator ended early\n");
1051 our_current_position++;
1053 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1054 app->data.application.id[0] = 'f'; /* twiddle the id */
1055 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1056 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1057 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1059 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1061 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1064 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1065 app->data.application.id[0] = 'g'; /* twiddle the id */
1066 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1067 return die_("setting APPLICATION data");
1068 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1069 return die_("copying object");
1070 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1071 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1073 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1076 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1077 app->data.application.id[0] = 'h'; /* twiddle the id */
1078 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1079 return die_("setting APPLICATION data");
1080 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1081 return die_("copying object");
1082 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1083 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1085 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1088 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1089 app->data.application.id[0] = 'i'; /* twiddle the id */
1090 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1091 return die_("setting APPLICATION data");
1092 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1093 return die_("copying object");
1094 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1095 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1096 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1098 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1101 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1102 app->data.application.id[0] = 'j'; /* twiddle the id */
1103 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1104 return die_("setting APPLICATION data");
1105 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1106 return die_("copying object");
1107 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1108 return die_("copying object");
1109 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1110 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1111 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1113 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1116 printf("SVA[A]PP\tnext\n");
1117 if(!FLAC__metadata_simple_iterator_next(iterator))
1118 return die_("iterator ended early\n");
1119 our_current_position++;
1121 printf("SVAA[P]P\tnext\n");
1122 if(!FLAC__metadata_simple_iterator_next(iterator))
1123 return die_("iterator ended early\n");
1124 our_current_position++;
1126 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1127 padding->length = 5;
1128 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1129 return die_("copying object");
1130 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1131 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1133 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1136 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1137 app->data.application.id[0] = 'k'; /* twiddle the id */
1138 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1139 return die_("copying object");
1140 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1141 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1143 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1146 printf("SVAAP[A]\tset PADDING (equal)\n");
1147 padding->length = 27;
1148 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1149 return die_("copying object");
1150 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1151 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1153 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1156 printf("SVAAP[P]\tprev\n");
1157 if(!FLAC__metadata_simple_iterator_prev(iterator))
1158 return die_("iterator ended early\n");
1159 our_current_position--;
1161 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1162 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1163 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1164 delete_from_our_metadata_(our_current_position--);
1166 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1169 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1170 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1171 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1172 delete_from_our_metadata_(our_current_position--);
1174 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1177 printf("SV[A]P\tnext\n");
1178 if(!FLAC__metadata_simple_iterator_next(iterator))
1179 return die_("iterator ended early\n");
1180 our_current_position++;
1182 printf("SVA[P]\tinsert PADDING after\n");
1183 padding->length = 5;
1184 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1185 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1186 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1189 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1192 printf("SVAP[P]\tprev\n");
1193 if(!FLAC__metadata_simple_iterator_prev(iterator))
1194 return die_("iterator ended early\n");
1195 our_current_position--;
1197 printf("SVA[P]P\tprev\n");
1198 if(!FLAC__metadata_simple_iterator_prev(iterator))
1199 return die_("iterator ended early\n");
1200 our_current_position--;
1202 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1203 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1204 return die_("setting APPLICATION data");
1205 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1206 return die_("copying object");
1207 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1208 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1210 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1213 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1214 if(!FLAC__metadata_object_application_set_data(app, data, 60, 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), expand into padding which will leave 0-length pad\n");
1225 if(!FLAC__metadata_object_application_set_data(app, data, 87, 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 our_metadata_.blocks[our_current_position+1]->length = 0;
1230 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1231 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1233 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1236 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1237 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1238 return die_("setting APPLICATION data");
1239 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1240 return die_("copying object");
1241 delete_from_our_metadata_(our_current_position+1);
1242 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1243 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1245 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1248 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1249 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1250 return die_("setting APPLICATION data");
1251 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1252 return die_("copying object");
1253 delete_from_our_metadata_(our_current_position+1);
1254 our_metadata_.blocks[our_current_position]->is_last = true;
1255 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1256 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1258 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1261 printf("SV[A]\tset PADDING (equal size)\n");
1262 padding->length = app->length;
1263 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1264 return die_("copying object");
1265 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1266 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1268 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1271 printf("SV[P]\tinsert PADDING after\n");
1272 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1273 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1274 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1277 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1280 printf("SVP[P]\tinsert PADDING after\n");
1281 padding->length = 5;
1282 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1283 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1284 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1287 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1290 printf("SVPP[P]\tprev\n");
1291 if(!FLAC__metadata_simple_iterator_prev(iterator))
1292 return die_("iterator ended early\n");
1293 our_current_position--;
1295 printf("SVP[P]P\tprev\n");
1296 if(!FLAC__metadata_simple_iterator_prev(iterator))
1297 return die_("iterator ended early\n");
1298 our_current_position--;
1300 printf("SV[P]PP\tprev\n");
1301 if(!FLAC__metadata_simple_iterator_prev(iterator))
1302 return die_("iterator ended early\n");
1303 our_current_position--;
1305 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1306 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1307 return die_("setting APPLICATION data");
1308 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1309 return die_("copying object");
1310 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1311 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1313 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1316 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1317 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1318 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1319 delete_from_our_metadata_(our_current_position--);
1321 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1324 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1325 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1326 return die_("setting APPLICATION data");
1327 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1328 return die_("copying object");
1329 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1330 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1332 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1335 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1336 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1337 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1338 delete_from_our_metadata_(our_current_position--);
1340 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1343 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1344 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1345 return die_("setting APPLICATION data");
1346 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1347 return die_("copying object");
1348 delete_from_our_metadata_(our_current_position+1);
1349 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1350 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1352 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1355 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1356 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1357 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1358 delete_from_our_metadata_(our_current_position--);
1360 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1363 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1364 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1365 return die_("setting APPLICATION data");
1366 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1367 return die_("copying object");
1368 our_metadata_.blocks[our_current_position+1]->length = 0;
1369 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1370 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1372 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1375 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1376 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1377 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1378 delete_from_our_metadata_(our_current_position--);
1380 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1383 printf("S[V]PP\tnext\n");
1384 if(!FLAC__metadata_simple_iterator_next(iterator))
1385 return die_("iterator ended early\n");
1386 our_current_position++;
1388 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1389 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1390 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1391 delete_from_our_metadata_(our_current_position--);
1393 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1396 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1397 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1398 return die_("setting APPLICATION data");
1399 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1400 return die_("copying object");
1401 delete_from_our_metadata_(our_current_position+1);
1402 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1403 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1405 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1408 printf("delete simple iterator\n");
1410 FLAC__metadata_simple_iterator_delete(iterator);
1412 FLAC__metadata_object_delete(app);
1413 FLAC__metadata_object_delete(padding);
1415 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1421 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1423 FLAC__Metadata_Iterator *iterator;
1424 FLAC__Metadata_Chain *chain;
1425 FLAC__StreamMetadata *block, *app, *padding;
1426 FLAC__byte data[2000];
1427 unsigned our_current_position;
1429 /* initialize 'data' to avoid Valgrind errors */
1430 memset(data, 0, sizeof(data));
1432 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1434 printf("generate read-only file\n");
1436 if(!generate_file_(/*include_extras=*/false, is_ogg))
1439 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1442 printf("create chain\n");
1444 if(0 == (chain = FLAC__metadata_chain_new()))
1445 return die_("allocating chain");
1447 printf("read chain\n");
1449 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1450 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1452 printf("[S]VP\ttest initial metadata\n");
1454 if(!compare_chain_(chain, 0, 0))
1456 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1462 printf("switch file to read-write\n");
1464 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1467 printf("create iterator\n");
1468 if(0 == (iterator = FLAC__metadata_iterator_new()))
1469 return die_("allocating memory for iterator");
1471 our_current_position = 0;
1473 FLAC__metadata_iterator_init(iterator, chain);
1475 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1476 return die_("getting block from iterator");
1478 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1480 printf("[S]VP\tmodify STREAMINFO, write\n");
1482 block->data.stream_info.sample_rate = 32000;
1483 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1484 return die_("copying object");
1486 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1487 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1488 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1490 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1493 printf("[S]VP\tnext\n");
1494 if(!FLAC__metadata_iterator_next(iterator))
1495 return die_("iterator ended early\n");
1496 our_current_position++;
1498 printf("S[V]P\tnext\n");
1499 if(!FLAC__metadata_iterator_next(iterator))
1500 return die_("iterator ended early\n");
1501 our_current_position++;
1503 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1504 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1505 return die_("getting block from iterator");
1506 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1507 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1508 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1509 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), 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, flacfilename(is_ogg)))
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_(is_ogg, decoder_metadata_callback_compare_))
1523 printf("SV[A]\tshrink 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, 26, 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, flacfilename(is_ogg)))
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_(is_ogg, decoder_metadata_callback_compare_))
1540 printf("SV[A]\tgrow APPLICATION, don't use 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, 28, 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, flacfilename(is_ogg)))
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_(is_ogg, decoder_metadata_callback_compare_))
1557 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\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, 36, 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=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1568 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1569 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1571 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1574 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1575 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1576 return die_("copying object");
1577 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1578 return die_("setting APPLICATION data");
1579 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1580 return die_("copying object");
1581 if(!FLAC__metadata_iterator_set_block(iterator, app))
1582 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1584 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1585 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1586 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1588 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1591 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1592 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1593 return die_("creating PADDING block");
1594 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1595 return die_("copying object");
1596 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1597 return die_("setting APPLICATION data");
1598 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1599 return die_("copying object");
1600 padding->length = 0;
1601 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1602 return die_("internal error");
1603 if(!FLAC__metadata_iterator_set_block(iterator, app))
1604 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1606 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1607 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1608 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1610 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1613 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1614 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1615 return die_("copying object");
1616 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1617 return die_("setting APPLICATION data");
1618 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1619 return die_("copying object");
1620 our_metadata_.blocks[our_current_position+1]->length = 13;
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, flacfilename(is_ogg)))
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_(is_ogg, decoder_metadata_callback_compare_))
1631 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\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, 50, 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 if(!FLAC__metadata_iterator_set_block(iterator, app))
1639 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1641 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1642 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1643 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1645 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1648 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1649 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1650 return die_("copying object");
1651 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1652 return die_("setting APPLICATION data");
1653 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1654 return die_("copying object");
1655 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1656 if(!FLAC__metadata_iterator_set_block(iterator, app))
1657 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1659 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1660 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1661 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1663 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1666 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1667 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1668 return die_("copying object");
1669 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1670 return die_("setting APPLICATION data");
1671 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1672 return die_("copying object");
1673 delete_from_our_metadata_(our_current_position+1);
1674 if(!FLAC__metadata_iterator_set_block(iterator, app))
1675 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1677 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1678 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1679 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1681 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1684 printf("SV[A]\tprev\n");
1685 if(!FLAC__metadata_iterator_prev(iterator))
1686 return die_("iterator ended early\n");
1687 our_current_position--;
1689 printf("S[V]A\tprev\n");
1690 if(!FLAC__metadata_iterator_prev(iterator))
1691 return die_("iterator ended early\n");
1692 our_current_position--;
1694 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1695 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1696 return die_("creating PADDING block");
1697 padding->length = 30;
1698 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1699 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1701 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1703 printf("[S]VP\tnext\n");
1704 if(!FLAC__metadata_iterator_next(iterator))
1705 return die_("iterator ended early\n");
1706 our_current_position++;
1708 printf("S[V]A\tinsert PADDING after\n");
1709 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1710 return die_("copying metadata");
1711 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1712 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1714 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1717 printf("SV[P]A\tinsert PADDING before\n");
1718 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1719 return die_("creating PADDING block");
1720 padding->length = 17;
1721 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1722 return die_("copying metadata");
1723 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1724 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1726 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1729 printf("SV[P]PA\tinsert PADDING before\n");
1730 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1731 return die_("creating PADDING block");
1732 padding->length = 0;
1733 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1734 return die_("copying metadata");
1735 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1736 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1738 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1741 printf("SV[P]PPA\tnext\n");
1742 if(!FLAC__metadata_iterator_next(iterator))
1743 return die_("iterator ended early\n");
1744 our_current_position++;
1746 printf("SVP[P]PA\tnext\n");
1747 if(!FLAC__metadata_iterator_next(iterator))
1748 return die_("iterator ended early\n");
1749 our_current_position++;
1751 printf("SVPP[P]A\tnext\n");
1752 if(!FLAC__metadata_iterator_next(iterator))
1753 return die_("iterator ended early\n");
1754 our_current_position++;
1756 printf("SVPPP[A]\tinsert PADDING after\n");
1757 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1758 return die_("creating PADDING block");
1759 padding->length = 57;
1760 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1761 return die_("copying metadata");
1762 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1763 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1765 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1768 printf("SVPPPA[P]\tinsert PADDING before\n");
1769 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1770 return die_("creating PADDING block");
1771 padding->length = 99;
1772 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1773 return die_("copying metadata");
1774 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1775 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1777 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1780 printf("delete iterator\n");
1781 FLAC__metadata_iterator_delete(iterator);
1782 our_current_position = 0;
1784 printf("SVPPPAPP\tmerge padding\n");
1785 FLAC__metadata_chain_merge_padding(chain);
1786 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1787 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1788 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1789 delete_from_our_metadata_(7);
1790 delete_from_our_metadata_(4);
1791 delete_from_our_metadata_(3);
1793 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1794 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1795 if(!compare_chain_(chain, 0, 0))
1797 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1800 printf("SVPAP\tsort padding\n");
1801 FLAC__metadata_chain_sort_padding(chain);
1802 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1803 delete_from_our_metadata_(2);
1805 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1806 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1807 if(!compare_chain_(chain, 0, 0))
1809 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1812 printf("create iterator\n");
1813 if(0 == (iterator = FLAC__metadata_iterator_new()))
1814 return die_("allocating memory for iterator");
1816 our_current_position = 0;
1818 FLAC__metadata_iterator_init(iterator, chain);
1820 printf("[S]VAP\tnext\n");
1821 if(!FLAC__metadata_iterator_next(iterator))
1822 return die_("iterator ended early\n");
1823 our_current_position++;
1825 printf("S[V]AP\tnext\n");
1826 if(!FLAC__metadata_iterator_next(iterator))
1827 return die_("iterator ended early\n");
1828 our_current_position++;
1830 printf("SV[A]P\tdelete middle block, replace with padding\n");
1831 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1832 return die_("creating PADDING block");
1833 padding->length = 71;
1834 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1835 return die_("copying object");
1836 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1837 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1839 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1842 printf("S[V]PP\tnext\n");
1843 if(!FLAC__metadata_iterator_next(iterator))
1844 return die_("iterator ended early\n");
1845 our_current_position++;
1847 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1848 delete_from_our_metadata_(our_current_position--);
1849 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1850 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", 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, replace with padding\n");
1861 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1862 return die_("creating PADDING block");
1863 padding->length = 219;
1864 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1865 return die_("copying object");
1866 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1867 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1869 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1872 printf("S[V]P\tnext\n");
1873 if(!FLAC__metadata_iterator_next(iterator))
1874 return die_("iterator ended early\n");
1875 our_current_position++;
1877 printf("SV[P]\tdelete last block, don't replace with padding\n");
1878 delete_from_our_metadata_(our_current_position--);
1879 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1880 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1882 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1885 printf("S[V]\tprev\n");
1886 if(!FLAC__metadata_iterator_prev(iterator))
1887 return die_("iterator ended early\n");
1888 our_current_position--;
1890 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1891 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1892 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1894 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1897 printf("delete iterator\n");
1898 FLAC__metadata_iterator_delete(iterator);
1899 our_current_position = 0;
1901 printf("SV\tmerge padding\n");
1902 FLAC__metadata_chain_merge_padding(chain);
1904 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1905 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1906 if(!compare_chain_(chain, 0, 0))
1908 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1911 printf("SV\tsort padding\n");
1912 FLAC__metadata_chain_sort_padding(chain);
1914 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1915 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1916 if(!compare_chain_(chain, 0, 0))
1918 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1922 printf("delete chain\n");
1924 FLAC__metadata_chain_delete(chain);
1926 if(!remove_file_(flacfilename(is_ogg)))
1932 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1934 FLAC__Metadata_Iterator *iterator;
1935 FLAC__Metadata_Chain *chain;
1936 FLAC__IOCallbacks callbacks;
1938 memset(&callbacks, 0, sizeof(callbacks));
1939 callbacks.read = (FLAC__IOCallback_Read)fread;
1940 #ifdef FLAC__VALGRIND_TESTING
1941 callbacks.write = chain_write_cb_;
1943 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1945 callbacks.seek = chain_seek_cb_;
1946 callbacks.tell = chain_tell_cb_;
1947 callbacks.eof = chain_eof_cb_;
1949 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1951 printf("generate file\n");
1953 if(!generate_file_(/*include_extras=*/false, is_ogg))
1956 printf("create chain\n");
1958 if(0 == (chain = FLAC__metadata_chain_new()))
1959 return die_("allocating chain");
1961 printf("read chain (filename-based)\n");
1963 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1964 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1966 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1968 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1969 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1970 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1971 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1972 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1975 printf("read chain (filename-based)\n");
1977 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1978 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1980 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1982 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1983 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1984 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1985 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1986 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1989 printf("read chain (callback-based)\n");
1991 FILE *file = fopen(flacfilename(is_ogg), "rb");
1993 return die_("opening file");
1994 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1996 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2001 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2003 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2004 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2005 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2006 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2007 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2010 printf("read chain (callback-based)\n");
2012 FILE *file = fopen(flacfilename(is_ogg), "rb");
2014 return die_("opening file");
2015 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2017 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2022 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2024 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2025 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2027 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2029 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2031 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2032 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2033 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2034 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2035 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2038 printf("read chain (callback-based)\n");
2040 FILE *file = fopen(flacfilename(is_ogg), "rb");
2042 return die_("opening file");
2043 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2045 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2050 printf("create iterator\n");
2051 if(0 == (iterator = FLAC__metadata_iterator_new()))
2052 return die_("allocating memory for iterator");
2054 FLAC__metadata_iterator_init(iterator, chain);
2056 printf("[S]VP\tnext\n");
2057 if(!FLAC__metadata_iterator_next(iterator))
2058 return die_("iterator ended early\n");
2060 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2061 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2062 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2064 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2066 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2067 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2069 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2071 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2073 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2074 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2075 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2076 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2077 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2080 printf("delete iterator\n");
2082 FLAC__metadata_iterator_delete(iterator);
2084 printf("delete chain\n");
2086 FLAC__metadata_chain_delete(chain);
2088 if(!remove_file_(flacfilename(is_ogg)))
2094 FLAC__bool test_metadata_file_manipulation()
2096 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2098 our_metadata_.num_blocks = 0;
2100 if(!test_level_0_())
2103 if(!test_level_1_())
2106 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2108 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2110 if(!test_level_2_misc_(/*is_ogg=*/false))
2113 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2115 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2118 /* when ogg flac write is supported, will have to add this: */
2119 if(!test_level_2_misc_(/*is_ogg=*/true))