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);
611 free(picture.data.picture.mime_type);
616 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
618 const char *filename = flacfilename(is_ogg);
619 FLAC__StreamDecoder *decoder;
620 decoder_client_struct decoder_client_data;
622 FLAC__ASSERT(0 != metadata_callback);
624 mc_our_block_number_ = 0;
625 decoder_client_data.error_occurred = false;
627 printf("\ttesting '%s'... ", filename);
630 if(0 == (decoder = FLAC__stream_decoder_new()))
631 return die_("couldn't allocate decoder instance");
633 FLAC__stream_decoder_set_md5_checking(decoder, true);
634 FLAC__stream_decoder_set_metadata_respond_all(decoder);
637 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
638 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
639 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
641 (void)FLAC__stream_decoder_finish(decoder);
642 FLAC__stream_decoder_delete(decoder);
643 return die_("initializing decoder\n");
645 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
646 (void)FLAC__stream_decoder_finish(decoder);
647 FLAC__stream_decoder_delete(decoder);
648 return die_("decoding file\n");
651 (void)FLAC__stream_decoder_finish(decoder);
652 FLAC__stream_decoder_delete(decoder);
654 if(decoder_client_data.error_occurred)
657 if(mc_our_block_number_ != our_metadata_.num_blocks)
658 return die_("short metadata block count");
664 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
666 if(!grabbag__file_change_stats(filename, read_only))
667 return die_("during grabbag__file_change_stats()");
672 static FLAC__bool remove_file_(const char *filename)
674 while(our_metadata_.num_blocks > 0)
675 delete_from_our_metadata_(0);
677 if(!grabbag__file_remove_file(filename))
678 return die_("removing file");
683 static FLAC__bool test_level_0_()
685 FLAC__StreamMetadata streaminfo;
686 FLAC__StreamMetadata *tags = 0;
687 FLAC__StreamMetadata *cuesheet = 0;
688 FLAC__StreamMetadata *picture = 0;
690 printf("\n\n++++++ testing level 0 interface\n");
692 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
695 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
698 printf("testing FLAC__metadata_get_streaminfo()... ");
700 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
701 return die_("during FLAC__metadata_get_streaminfo()");
703 /* check to see if some basic data matches (c.f. generate_file_()) */
704 if(streaminfo.data.stream_info.channels != 1)
705 return die_("mismatch in streaminfo.data.stream_info.channels");
706 if(streaminfo.data.stream_info.bits_per_sample != 8)
707 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
708 if(streaminfo.data.stream_info.sample_rate != 44100)
709 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
710 if(streaminfo.data.stream_info.min_blocksize != 576)
711 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
712 if(streaminfo.data.stream_info.max_blocksize != 576)
713 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
717 printf("testing FLAC__metadata_get_tags()... ");
719 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
720 return die_("during FLAC__metadata_get_tags()");
722 /* check to see if some basic data matches (c.f. generate_file_()) */
723 if(tags->data.vorbis_comment.num_comments != 0)
724 return die_("mismatch in tags->data.vorbis_comment.num_comments");
728 FLAC__metadata_object_delete(tags);
730 printf("testing FLAC__metadata_get_cuesheet()... ");
732 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
733 return die_("during FLAC__metadata_get_cuesheet()");
735 /* check to see if some basic data matches (c.f. generate_file_()) */
736 if(cuesheet->data.cue_sheet.lead_in != 123)
737 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
741 FLAC__metadata_object_delete(cuesheet);
743 printf("testing FLAC__metadata_get_picture()... ");
745 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)))
746 return die_("during FLAC__metadata_get_picture()");
748 /* check to see if some basic data matches (c.f. generate_file_()) */
749 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
750 return die_("mismatch in picture->data.picture.type");
754 FLAC__metadata_object_delete(picture);
756 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
762 static FLAC__bool test_level_1_()
764 FLAC__Metadata_SimpleIterator *iterator;
765 FLAC__StreamMetadata *block, *app, *padding;
766 FLAC__byte data[1000];
767 unsigned our_current_position = 0;
769 /* initialize 'data' to avoid Valgrind errors */
770 memset(data, 0, sizeof(data));
772 printf("\n\n++++++ testing level 1 interface\n");
774 /************************************************************/
776 printf("simple iterator on read-only file\n");
778 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
781 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
784 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
787 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
788 return die_("FLAC__metadata_simple_iterator_new()");
790 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
791 return die_("FLAC__metadata_simple_iterator_init() returned false");
793 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
794 if(FLAC__metadata_simple_iterator_is_writable(iterator))
795 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
797 printf("iterate forwards\n");
799 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
800 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
801 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
802 return die_("getting block 0");
803 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
804 return die_("expected STREAMINFO type");
806 return die_("expected is_last to be false");
807 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
808 return die_("bad STREAMINFO length");
809 /* check to see if some basic data matches (c.f. generate_file_()) */
810 if(block->data.stream_info.channels != 1)
811 return die_("mismatch in channels");
812 if(block->data.stream_info.bits_per_sample != 8)
813 return die_("mismatch in bits_per_sample");
814 if(block->data.stream_info.sample_rate != 44100)
815 return die_("mismatch in sample_rate");
816 if(block->data.stream_info.min_blocksize != 576)
817 return die_("mismatch in min_blocksize");
818 if(block->data.stream_info.max_blocksize != 576)
819 return die_("mismatch in max_blocksize");
820 FLAC__metadata_object_delete(block);
822 if(!FLAC__metadata_simple_iterator_next(iterator))
823 return die_("forward iterator ended early");
824 our_current_position++;
826 if(!FLAC__metadata_simple_iterator_next(iterator))
827 return die_("forward iterator ended early");
828 our_current_position++;
830 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
831 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
832 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
833 return die_("getting block 2");
834 if(block->type != FLAC__METADATA_TYPE_PADDING)
835 return die_("expected PADDING type");
837 return die_("expected is_last to be true");
838 /* check to see if some basic data matches (c.f. generate_file_()) */
839 if(block->length != 1234)
840 return die_("bad PADDING length");
841 FLAC__metadata_object_delete(block);
843 if(FLAC__metadata_simple_iterator_next(iterator))
844 return die_("forward iterator returned true but should have returned false");
846 printf("iterate backwards\n");
847 if(!FLAC__metadata_simple_iterator_prev(iterator))
848 return die_("reverse iterator ended early");
849 if(!FLAC__metadata_simple_iterator_prev(iterator))
850 return die_("reverse iterator ended early");
851 if(FLAC__metadata_simple_iterator_prev(iterator))
852 return die_("reverse iterator returned true but should have returned false");
854 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
856 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
857 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
859 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
861 FLAC__metadata_simple_iterator_delete(iterator);
863 /************************************************************/
865 printf("simple iterator on writable file\n");
867 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
870 printf("creating APPLICATION block\n");
872 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
873 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
874 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
876 printf("creating PADDING block\n");
878 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
879 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
880 padding->length = 20;
882 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
883 return die_("FLAC__metadata_simple_iterator_new()");
885 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
886 return die_("FLAC__metadata_simple_iterator_init() returned false");
887 our_current_position = 0;
889 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
891 printf("[S]VP\ttry to write over STREAMINFO block...\n");
892 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
893 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
895 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
897 printf("[S]VP\tnext\n");
898 if(!FLAC__metadata_simple_iterator_next(iterator))
899 return die_("iterator ended early\n");
900 our_current_position++;
902 printf("S[V]P\tnext\n");
903 if(!FLAC__metadata_simple_iterator_next(iterator))
904 return die_("iterator ended early\n");
905 our_current_position++;
907 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
908 padding->length = 25;
909 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
910 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
911 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
914 printf("SVP[P]\tprev\n");
915 if(!FLAC__metadata_simple_iterator_prev(iterator))
916 return die_("iterator ended early\n");
917 our_current_position--;
919 printf("SV[P]P\tprev\n");
920 if(!FLAC__metadata_simple_iterator_prev(iterator))
921 return die_("iterator ended early\n");
922 our_current_position--;
924 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
925 padding->length = 30;
926 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
927 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
928 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
931 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
934 printf("SV[P]PP\tprev\n");
935 if(!FLAC__metadata_simple_iterator_prev(iterator))
936 return die_("iterator ended early\n");
937 our_current_position--;
939 printf("S[V]PPP\tprev\n");
940 if(!FLAC__metadata_simple_iterator_prev(iterator))
941 return die_("iterator ended early\n");
942 our_current_position--;
944 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
945 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
946 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
948 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
951 printf("[S]VPPP\tnext\n");
952 if(!FLAC__metadata_simple_iterator_next(iterator))
953 return die_("iterator ended early\n");
954 our_current_position++;
956 printf("S[V]PPP\tnext\n");
957 if(!FLAC__metadata_simple_iterator_next(iterator))
958 return die_("iterator ended early\n");
959 our_current_position++;
961 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
962 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
963 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
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), don't replace with padding\n");
972 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
973 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
974 delete_from_our_metadata_(our_current_position--);
976 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
979 printf("S[V]PP\tnext\n");
980 if(!FLAC__metadata_simple_iterator_next(iterator))
981 return die_("iterator ended early\n");
982 our_current_position++;
984 printf("SV[P]P\tnext\n");
985 if(!FLAC__metadata_simple_iterator_next(iterator))
986 return die_("iterator ended early\n");
987 our_current_position++;
989 printf("SVP[P]\tdelete (last block), replace with padding\n");
990 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
991 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
992 our_current_position--;
994 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
997 printf("SV[P]P\tnext\n");
998 if(!FLAC__metadata_simple_iterator_next(iterator))
999 return die_("iterator ended early\n");
1000 our_current_position++;
1002 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1003 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1004 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1005 delete_from_our_metadata_(our_current_position--);
1007 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1010 printf("SV[P]\tprev\n");
1011 if(!FLAC__metadata_simple_iterator_prev(iterator))
1012 return die_("iterator ended early\n");
1013 our_current_position--;
1015 printf("S[V]P\tprev\n");
1016 if(!FLAC__metadata_simple_iterator_prev(iterator))
1017 return die_("iterator ended early\n");
1018 our_current_position--;
1020 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1021 FLAC__ASSERT(our_current_position == 0);
1022 block = FLAC__metadata_simple_iterator_get_block(iterator);
1023 block->data.stream_info.sample_rate = 32000;
1024 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1025 return die_("copying object");
1026 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1027 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1028 FLAC__metadata_object_delete(block);
1030 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1033 printf("[S]VP\tnext\n");
1034 if(!FLAC__metadata_simple_iterator_next(iterator))
1035 return die_("iterator ended early\n");
1036 our_current_position++;
1038 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1039 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1040 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1041 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1042 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1044 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1046 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1049 printf("SV[A]P\tnext\n");
1050 if(!FLAC__metadata_simple_iterator_next(iterator))
1051 return die_("iterator ended early\n");
1052 our_current_position++;
1054 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1055 app->data.application.id[0] = 'f'; /* twiddle the id */
1056 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1057 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1058 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1060 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1062 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1065 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1066 app->data.application.id[0] = 'g'; /* twiddle the id */
1067 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1068 return die_("setting APPLICATION data");
1069 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1070 return die_("copying object");
1071 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1072 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1074 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1077 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1078 app->data.application.id[0] = 'h'; /* twiddle the id */
1079 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1080 return die_("setting APPLICATION data");
1081 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1082 return die_("copying object");
1083 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1084 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1086 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1089 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1090 app->data.application.id[0] = 'i'; /* twiddle the id */
1091 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1092 return die_("setting APPLICATION data");
1093 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1094 return die_("copying object");
1095 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1096 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1097 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1099 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1102 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1103 app->data.application.id[0] = 'j'; /* twiddle the id */
1104 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1105 return die_("setting APPLICATION data");
1106 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1107 return die_("copying object");
1108 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1109 return die_("copying object");
1110 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1111 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1112 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1114 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1117 printf("SVA[A]PP\tnext\n");
1118 if(!FLAC__metadata_simple_iterator_next(iterator))
1119 return die_("iterator ended early\n");
1120 our_current_position++;
1122 printf("SVAA[P]P\tnext\n");
1123 if(!FLAC__metadata_simple_iterator_next(iterator))
1124 return die_("iterator ended early\n");
1125 our_current_position++;
1127 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1128 padding->length = 5;
1129 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1130 return die_("copying object");
1131 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1132 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1134 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1137 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1138 app->data.application.id[0] = 'k'; /* twiddle the id */
1139 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1140 return die_("copying object");
1141 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1142 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1144 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1147 printf("SVAAP[A]\tset PADDING (equal)\n");
1148 padding->length = 27;
1149 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1150 return die_("copying object");
1151 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1152 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1154 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1157 printf("SVAAP[P]\tprev\n");
1158 if(!FLAC__metadata_simple_iterator_prev(iterator))
1159 return die_("iterator ended early\n");
1160 our_current_position--;
1162 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1163 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1164 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1165 delete_from_our_metadata_(our_current_position--);
1167 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1170 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1171 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1172 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1173 delete_from_our_metadata_(our_current_position--);
1175 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1178 printf("SV[A]P\tnext\n");
1179 if(!FLAC__metadata_simple_iterator_next(iterator))
1180 return die_("iterator ended early\n");
1181 our_current_position++;
1183 printf("SVA[P]\tinsert PADDING after\n");
1184 padding->length = 5;
1185 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1186 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1187 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1190 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1193 printf("SVAP[P]\tprev\n");
1194 if(!FLAC__metadata_simple_iterator_prev(iterator))
1195 return die_("iterator ended early\n");
1196 our_current_position--;
1198 printf("SVA[P]P\tprev\n");
1199 if(!FLAC__metadata_simple_iterator_prev(iterator))
1200 return die_("iterator ended early\n");
1201 our_current_position--;
1203 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1204 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1205 return die_("setting APPLICATION data");
1206 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1207 return die_("copying object");
1208 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1209 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1211 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1214 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1215 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1216 return die_("setting APPLICATION data");
1217 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1218 return die_("copying object");
1219 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1220 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1222 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1225 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1226 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1227 return die_("setting APPLICATION data");
1228 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1229 return die_("copying object");
1230 our_metadata_.blocks[our_current_position+1]->length = 0;
1231 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1232 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1234 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1237 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1238 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1239 return die_("setting APPLICATION data");
1240 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1241 return die_("copying object");
1242 delete_from_our_metadata_(our_current_position+1);
1243 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1244 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1246 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1249 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1250 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1251 return die_("setting APPLICATION data");
1252 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1253 return die_("copying object");
1254 delete_from_our_metadata_(our_current_position+1);
1255 our_metadata_.blocks[our_current_position]->is_last = true;
1256 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1257 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1259 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1262 printf("SV[A]\tset PADDING (equal size)\n");
1263 padding->length = app->length;
1264 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1265 return die_("copying object");
1266 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1267 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1269 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1272 printf("SV[P]\tinsert PADDING after\n");
1273 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1274 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1275 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1278 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1281 printf("SVP[P]\tinsert PADDING after\n");
1282 padding->length = 5;
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("SVPP[P]\tprev\n");
1292 if(!FLAC__metadata_simple_iterator_prev(iterator))
1293 return die_("iterator ended early\n");
1294 our_current_position--;
1296 printf("SVP[P]P\tprev\n");
1297 if(!FLAC__metadata_simple_iterator_prev(iterator))
1298 return die_("iterator ended early\n");
1299 our_current_position--;
1301 printf("SV[P]PP\tprev\n");
1302 if(!FLAC__metadata_simple_iterator_prev(iterator))
1303 return die_("iterator ended early\n");
1304 our_current_position--;
1306 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1307 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1308 return die_("setting APPLICATION data");
1309 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1310 return die_("copying object");
1311 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1312 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1314 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1317 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1318 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1319 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1320 delete_from_our_metadata_(our_current_position--);
1322 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1325 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1326 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1327 return die_("setting APPLICATION data");
1328 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1329 return die_("copying object");
1330 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1331 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1333 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1336 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1337 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1338 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1339 delete_from_our_metadata_(our_current_position--);
1341 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1344 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1345 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1346 return die_("setting APPLICATION data");
1347 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1348 return die_("copying object");
1349 delete_from_our_metadata_(our_current_position+1);
1350 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1351 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1353 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1356 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1357 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1358 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1359 delete_from_our_metadata_(our_current_position--);
1361 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1364 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1365 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1366 return die_("setting APPLICATION data");
1367 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1368 return die_("copying object");
1369 our_metadata_.blocks[our_current_position+1]->length = 0;
1370 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1371 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1373 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1376 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1377 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1378 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1379 delete_from_our_metadata_(our_current_position--);
1381 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1384 printf("S[V]PP\tnext\n");
1385 if(!FLAC__metadata_simple_iterator_next(iterator))
1386 return die_("iterator ended early\n");
1387 our_current_position++;
1389 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1390 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1391 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1392 delete_from_our_metadata_(our_current_position--);
1394 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1397 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1398 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1399 return die_("setting APPLICATION data");
1400 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1401 return die_("copying object");
1402 delete_from_our_metadata_(our_current_position+1);
1403 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1404 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1406 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1409 printf("delete simple iterator\n");
1411 FLAC__metadata_simple_iterator_delete(iterator);
1413 FLAC__metadata_object_delete(app);
1414 FLAC__metadata_object_delete(padding);
1416 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1422 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1424 FLAC__Metadata_Iterator *iterator;
1425 FLAC__Metadata_Chain *chain;
1426 FLAC__StreamMetadata *block, *app, *padding;
1427 FLAC__byte data[2000];
1428 unsigned our_current_position;
1430 /* initialize 'data' to avoid Valgrind errors */
1431 memset(data, 0, sizeof(data));
1433 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1435 printf("generate read-only file\n");
1437 if(!generate_file_(/*include_extras=*/false, is_ogg))
1440 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1443 printf("create chain\n");
1445 if(0 == (chain = FLAC__metadata_chain_new()))
1446 return die_("allocating chain");
1448 printf("read chain\n");
1450 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1451 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1453 printf("[S]VP\ttest initial metadata\n");
1455 if(!compare_chain_(chain, 0, 0))
1457 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1463 printf("switch file to read-write\n");
1465 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1468 printf("create iterator\n");
1469 if(0 == (iterator = FLAC__metadata_iterator_new()))
1470 return die_("allocating memory for iterator");
1472 our_current_position = 0;
1474 FLAC__metadata_iterator_init(iterator, chain);
1476 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1477 return die_("getting block from iterator");
1479 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1481 printf("[S]VP\tmodify STREAMINFO, write\n");
1483 block->data.stream_info.sample_rate = 32000;
1484 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1485 return die_("copying object");
1487 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1488 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1489 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1491 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1494 printf("[S]VP\tnext\n");
1495 if(!FLAC__metadata_iterator_next(iterator))
1496 return die_("iterator ended early\n");
1497 our_current_position++;
1499 printf("S[V]P\tnext\n");
1500 if(!FLAC__metadata_iterator_next(iterator))
1501 return die_("iterator ended early\n");
1502 our_current_position++;
1504 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1505 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1506 return die_("getting block from iterator");
1507 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1508 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1509 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1510 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1511 return die_("setting APPLICATION data");
1512 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1513 return die_("copying object");
1514 if(!FLAC__metadata_iterator_set_block(iterator, app))
1515 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1517 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1518 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1519 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1521 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1524 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1525 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1526 return die_("copying object");
1527 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1528 return die_("setting APPLICATION data");
1529 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1530 return die_("copying object");
1531 if(!FLAC__metadata_iterator_set_block(iterator, app))
1532 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1534 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1535 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1536 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1538 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1541 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1542 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1543 return die_("copying object");
1544 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1545 return die_("setting APPLICATION data");
1546 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1547 return die_("copying object");
1548 if(!FLAC__metadata_iterator_set_block(iterator, app))
1549 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1551 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1552 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1553 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1555 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1558 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1559 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1560 return die_("copying object");
1561 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1562 return die_("setting APPLICATION data");
1563 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1564 return die_("copying object");
1565 if(!FLAC__metadata_iterator_set_block(iterator, app))
1566 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1568 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1569 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1570 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1572 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1575 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1576 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1577 return die_("copying object");
1578 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1579 return die_("setting APPLICATION data");
1580 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1581 return die_("copying object");
1582 if(!FLAC__metadata_iterator_set_block(iterator, app))
1583 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1585 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1586 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1587 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1589 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1592 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1593 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1594 return die_("creating PADDING block");
1595 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1596 return die_("copying object");
1597 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1598 return die_("setting APPLICATION data");
1599 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1600 return die_("copying object");
1601 padding->length = 0;
1602 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1603 return die_("internal error");
1604 if(!FLAC__metadata_iterator_set_block(iterator, app))
1605 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1607 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1608 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1609 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1611 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1614 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1615 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1616 return die_("copying object");
1617 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1618 return die_("setting APPLICATION data");
1619 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1620 return die_("copying object");
1621 our_metadata_.blocks[our_current_position+1]->length = 13;
1622 if(!FLAC__metadata_iterator_set_block(iterator, app))
1623 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1625 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1626 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1627 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1629 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1632 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1633 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1634 return die_("copying object");
1635 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1636 return die_("setting APPLICATION data");
1637 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1638 return die_("copying object");
1639 if(!FLAC__metadata_iterator_set_block(iterator, app))
1640 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1642 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1643 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1644 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1646 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1649 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1650 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1651 return die_("copying object");
1652 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1653 return die_("setting APPLICATION data");
1654 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1655 return die_("copying object");
1656 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1657 if(!FLAC__metadata_iterator_set_block(iterator, app))
1658 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1660 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1661 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1662 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1664 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1667 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1668 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1669 return die_("copying object");
1670 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1671 return die_("setting APPLICATION data");
1672 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1673 return die_("copying object");
1674 delete_from_our_metadata_(our_current_position+1);
1675 if(!FLAC__metadata_iterator_set_block(iterator, app))
1676 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1678 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1679 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1680 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1682 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1685 printf("SV[A]\tprev\n");
1686 if(!FLAC__metadata_iterator_prev(iterator))
1687 return die_("iterator ended early\n");
1688 our_current_position--;
1690 printf("S[V]A\tprev\n");
1691 if(!FLAC__metadata_iterator_prev(iterator))
1692 return die_("iterator ended early\n");
1693 our_current_position--;
1695 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1696 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1697 return die_("creating PADDING block");
1698 padding->length = 30;
1699 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1700 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1702 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1704 printf("[S]VP\tnext\n");
1705 if(!FLAC__metadata_iterator_next(iterator))
1706 return die_("iterator ended early\n");
1707 our_current_position++;
1709 printf("S[V]A\tinsert PADDING after\n");
1710 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1711 return die_("copying metadata");
1712 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1713 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1715 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1718 printf("SV[P]A\tinsert PADDING before\n");
1719 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1720 return die_("creating PADDING block");
1721 padding->length = 17;
1722 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1723 return die_("copying metadata");
1724 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1725 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1727 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1730 printf("SV[P]PA\tinsert PADDING before\n");
1731 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1732 return die_("creating PADDING block");
1733 padding->length = 0;
1734 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1735 return die_("copying metadata");
1736 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1737 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1739 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1742 printf("SV[P]PPA\tnext\n");
1743 if(!FLAC__metadata_iterator_next(iterator))
1744 return die_("iterator ended early\n");
1745 our_current_position++;
1747 printf("SVP[P]PA\tnext\n");
1748 if(!FLAC__metadata_iterator_next(iterator))
1749 return die_("iterator ended early\n");
1750 our_current_position++;
1752 printf("SVPP[P]A\tnext\n");
1753 if(!FLAC__metadata_iterator_next(iterator))
1754 return die_("iterator ended early\n");
1755 our_current_position++;
1757 printf("SVPPP[A]\tinsert PADDING after\n");
1758 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1759 return die_("creating PADDING block");
1760 padding->length = 57;
1761 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1762 return die_("copying metadata");
1763 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1764 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1766 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1769 printf("SVPPPA[P]\tinsert PADDING before\n");
1770 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1771 return die_("creating PADDING block");
1772 padding->length = 99;
1773 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1774 return die_("copying metadata");
1775 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1776 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1778 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1781 printf("delete iterator\n");
1782 FLAC__metadata_iterator_delete(iterator);
1783 our_current_position = 0;
1785 printf("SVPPPAPP\tmerge padding\n");
1786 FLAC__metadata_chain_merge_padding(chain);
1787 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1788 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1789 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1790 delete_from_our_metadata_(7);
1791 delete_from_our_metadata_(4);
1792 delete_from_our_metadata_(3);
1794 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1795 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1796 if(!compare_chain_(chain, 0, 0))
1798 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1801 printf("SVPAP\tsort padding\n");
1802 FLAC__metadata_chain_sort_padding(chain);
1803 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1804 delete_from_our_metadata_(2);
1806 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1807 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1808 if(!compare_chain_(chain, 0, 0))
1810 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1813 printf("create iterator\n");
1814 if(0 == (iterator = FLAC__metadata_iterator_new()))
1815 return die_("allocating memory for iterator");
1817 our_current_position = 0;
1819 FLAC__metadata_iterator_init(iterator, chain);
1821 printf("[S]VAP\tnext\n");
1822 if(!FLAC__metadata_iterator_next(iterator))
1823 return die_("iterator ended early\n");
1824 our_current_position++;
1826 printf("S[V]AP\tnext\n");
1827 if(!FLAC__metadata_iterator_next(iterator))
1828 return die_("iterator ended early\n");
1829 our_current_position++;
1831 printf("SV[A]P\tdelete middle block, replace with padding\n");
1832 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1833 return die_("creating PADDING block");
1834 padding->length = 71;
1835 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1836 return die_("copying object");
1837 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1838 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1840 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1843 printf("S[V]PP\tnext\n");
1844 if(!FLAC__metadata_iterator_next(iterator))
1845 return die_("iterator ended early\n");
1846 our_current_position++;
1848 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1849 delete_from_our_metadata_(our_current_position--);
1850 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1851 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1853 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1856 printf("S[V]P\tnext\n");
1857 if(!FLAC__metadata_iterator_next(iterator))
1858 return die_("iterator ended early\n");
1859 our_current_position++;
1861 printf("SV[P]\tdelete last block, replace with padding\n");
1862 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1863 return die_("creating PADDING block");
1864 padding->length = 219;
1865 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1866 return die_("copying object");
1867 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1868 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1870 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1873 printf("S[V]P\tnext\n");
1874 if(!FLAC__metadata_iterator_next(iterator))
1875 return die_("iterator ended early\n");
1876 our_current_position++;
1878 printf("SV[P]\tdelete last block, don't replace with padding\n");
1879 delete_from_our_metadata_(our_current_position--);
1880 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1881 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1883 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1886 printf("S[V]\tprev\n");
1887 if(!FLAC__metadata_iterator_prev(iterator))
1888 return die_("iterator ended early\n");
1889 our_current_position--;
1891 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1892 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1893 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1895 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1898 printf("delete iterator\n");
1899 FLAC__metadata_iterator_delete(iterator);
1900 our_current_position = 0;
1902 printf("SV\tmerge padding\n");
1903 FLAC__metadata_chain_merge_padding(chain);
1905 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1906 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1907 if(!compare_chain_(chain, 0, 0))
1909 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1912 printf("SV\tsort padding\n");
1913 FLAC__metadata_chain_sort_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_))
1923 printf("delete chain\n");
1925 FLAC__metadata_chain_delete(chain);
1927 if(!remove_file_(flacfilename(is_ogg)))
1933 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1935 FLAC__Metadata_Iterator *iterator;
1936 FLAC__Metadata_Chain *chain;
1937 FLAC__IOCallbacks callbacks;
1939 memset(&callbacks, 0, sizeof(callbacks));
1940 callbacks.read = (FLAC__IOCallback_Read)fread;
1941 #ifdef FLAC__VALGRIND_TESTING
1942 callbacks.write = chain_write_cb_;
1944 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1946 callbacks.seek = chain_seek_cb_;
1947 callbacks.tell = chain_tell_cb_;
1948 callbacks.eof = chain_eof_cb_;
1950 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1952 printf("generate file\n");
1954 if(!generate_file_(/*include_extras=*/false, is_ogg))
1957 printf("create chain\n");
1959 if(0 == (chain = FLAC__metadata_chain_new()))
1960 return die_("allocating chain");
1962 printf("read chain (filename-based)\n");
1964 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1965 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1967 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1969 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1970 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1971 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1972 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1973 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1976 printf("read chain (filename-based)\n");
1978 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1979 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1981 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1983 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1984 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1985 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1986 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1987 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1990 printf("read chain (callback-based)\n");
1992 FILE *file = fopen(flacfilename(is_ogg), "rb");
1994 return die_("opening file");
1995 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
1997 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2002 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2004 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2005 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2006 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2007 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2008 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2011 printf("read chain (callback-based)\n");
2013 FILE *file = fopen(flacfilename(is_ogg), "rb");
2015 return die_("opening file");
2016 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2018 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2023 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2025 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2026 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2028 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2030 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2032 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2033 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2034 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2035 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2036 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2039 printf("read chain (callback-based)\n");
2041 FILE *file = fopen(flacfilename(is_ogg), "rb");
2043 return die_("opening file");
2044 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2046 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2051 printf("create iterator\n");
2052 if(0 == (iterator = FLAC__metadata_iterator_new()))
2053 return die_("allocating memory for iterator");
2055 FLAC__metadata_iterator_init(iterator, chain);
2057 printf("[S]VP\tnext\n");
2058 if(!FLAC__metadata_iterator_next(iterator))
2059 return die_("iterator ended early\n");
2061 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2062 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2063 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2065 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2067 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2068 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2070 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2072 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2074 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2075 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2076 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2077 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2078 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2081 printf("delete iterator\n");
2083 FLAC__metadata_iterator_delete(iterator);
2085 printf("delete chain\n");
2087 FLAC__metadata_chain_delete(chain);
2089 if(!remove_file_(flacfilename(is_ogg)))
2095 FLAC__bool test_metadata_file_manipulation()
2097 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2099 our_metadata_.num_blocks = 0;
2101 if(!test_level_0_())
2104 if(!test_level_1_())
2107 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2109 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2111 if(!test_level_2_misc_(/*is_ogg=*/false))
2114 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2116 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2119 /* when ogg flac write is supported, will have to add this: */
2120 if(!test_level_2_misc_(/*is_ogg=*/true))