Fix a couple of Windows 2Gig file size issues.
[flac.git] / src / test_libFLAC / metadata_manip.c
blobea51d1728fa96b095e10a9dbe97f2b1c22efb9c5
1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h> /* for malloc() */
25 #include <string.h> /* for memcpy()/memset() */
26 #if defined _MSC_VER || defined __MINGW32__
27 #include <sys/utime.h> /* for utime() */
28 #include <io.h> /* for chmod() */
29 #else
30 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
31 #include <utime.h> /* for utime() */
32 #include <unistd.h> /* for chown(), unlink() */
33 #endif
34 #include <sys/stat.h> /* for stat(), maybe chmod() */
35 #include "FLAC/assert.h"
36 #include "FLAC/stream_decoder.h"
37 #include "FLAC/metadata.h"
38 #include "share/grabbag.h"
39 #include "share/compat.h"
40 #include "share/macros.h"
41 #include "test_libs_common/file_utils_flac.h"
42 #include "test_libs_common/metadata_utils.h"
43 #include "metadata.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 ******************************************************************************/
57 typedef struct {
58 FLAC__bool error_occurred;
59 } decoder_client_struct;
61 typedef struct {
62 FLAC__StreamMetadata *blocks[64];
63 unsigned num_blocks;
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.oga" : "metadata.flac";
77 static FLAC__bool die_(const char *msg)
79 printf("ERROR: %s\n", msg);
80 return false;
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]);
87 return false;
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)]);
94 return false;
97 static void *malloc_or_die_(size_t size)
99 void *x = malloc(size);
100 if(0 == x) {
101 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
102 exit(1);
104 return x;
107 static char *strdup_or_die_(const char *s)
109 char *x = strdup(s);
110 if(0 == x) {
111 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
112 exit(1);
114 return x;
117 /* functions for working with our metadata copy */
119 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
121 unsigned i;
122 FLAC__StreamMetadata *obj = block;
123 FLAC__ASSERT(position < our_metadata_.num_blocks);
124 if(copy) {
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;
136 return true;
139 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
141 unsigned i;
142 FLAC__StreamMetadata *obj = block;
143 if(copy) {
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;
150 else {
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;
162 return true;
165 static void delete_from_our_metadata_(unsigned position)
167 unsigned i;
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 static FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
188 static const char *tempfile_suffix = ".metadata_edit";
190 if(0 == (*tempfilename = malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
191 return false;
192 strcpy(*tempfilename, filename);
193 strcat(*tempfilename, tempfile_suffix);
195 if(0 == (*tempfile = fopen(*tempfilename, "wb")))
196 return false;
198 return true;
201 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
203 if(0 != *tempfile) {
204 (void)fclose(*tempfile);
205 *tempfile = 0;
208 if(0 != *tempfilename) {
209 (void)unlink(*tempfilename);
210 free(*tempfilename);
211 *tempfilename = 0;
215 static 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);
222 if(0 != *tempfile) {
223 (void)fclose(*tempfile);
224 *tempfile = 0;
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);
231 return false;
233 #endif
235 if(0 != rename(*tempfilename, filename)) {
236 cleanup_tempfile_(tempfile, tempfilename);
237 return false;
240 cleanup_tempfile_(tempfile, tempfilename);
242 return true;
245 static 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 static 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__
264 FLAC_CHECK_RETURN(chown(filename, stats->st_uid, -1));
265 FLAC_CHECK_RETURN(chown(filename, -1, stats->st_gid));
266 #endif
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);
274 if(!ferror(stream))
275 fflush(stream);
276 return ret;
278 #endif
280 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
282 FLAC__off_t o = (FLAC__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)
299 if(filename_based)
300 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
301 else {
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_;
308 #else
309 callbacks.write = (FLAC__IOCallback_Write)fwrite;
310 #endif
311 callbacks.seek = chain_seek_cb_;
312 callbacks.eof = chain_eof_cb_;
314 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
315 struct stat stats;
316 FILE *file, *tempfile = 0;
317 char *tempfilename;
318 if(preserve_file_stats) {
319 if(!get_file_stats_(filename, &stats))
320 return false;
322 if(0 == (file = fopen(filename, "rb")))
323 return false; /*@@@@ chain status still says OK though */
324 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
325 fclose(file);
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)) {
330 fclose(file);
331 fclose(tempfile);
332 return false;
334 fclose(file);
335 fclose(tempfile);
336 file = tempfile = 0;
337 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
338 return false;
339 if(preserve_file_stats)
340 set_file_stats_(filename, &stats);
342 else {
343 FILE *file = fopen(filename, "r+b");
344 if(0 == file)
345 return false; /*@@@@ chain status still says OK though */
346 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
347 return false;
348 fclose(file);
352 return true;
355 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based, FLAC__bool is_ogg)
357 if(filename_based)
358 return is_ogg?
359 FLAC__metadata_chain_read_ogg(chain, flacfilename(is_ogg)) :
360 FLAC__metadata_chain_read(chain, flacfilename(is_ogg))
362 else {
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_;
371 FLAC__bool ret;
372 FILE *file = fopen(filename, "rb");
373 if(0 == file)
374 return false; /*@@@@ chain status still says OK though */
375 ret = is_ogg?
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)
379 fclose(file);
380 return ret;
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)
389 unsigned i;
390 FLAC__Metadata_Iterator *iterator;
391 FLAC__StreamMetadata *block;
392 FLAC__bool next_ok = true;
394 FLAC__ASSERT(0 != chain);
396 printf("\tcomparing chain... ");
397 fflush(stdout);
399 if(0 == (iterator = FLAC__metadata_iterator_new()))
400 return die_("allocating memory for iterator");
402 FLAC__metadata_iterator_init(iterator, chain);
404 i = 0;
405 do {
406 printf("%u... ", i);
407 fflush(stdout);
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");
419 i++;
420 next_ok = FLAC__metadata_iterator_next(iterator);
421 } while(i < our_metadata_.num_blocks && next_ok);
423 FLAC__metadata_iterator_delete(iterator);
425 if(next_ok)
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... ");
433 fflush(stdout);
435 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
436 return die_("metadata block mismatch");
439 printf("PASSED\n");
441 return true;
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... ");
455 fflush(stdout);
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_);
467 fflush(stdout);
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;
477 (void)decoder;
479 /* don't bother checking if we've already hit an error */
480 if(dcd->error_occurred)
481 return;
483 printf("%d... ", mc_our_block_number_);
484 fflush(stdout);
486 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
487 (void)die_("got more metadata blocks than expected");
488 dcd->error_occurred = true;
490 else {
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;
502 (void)decoder;
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;
561 picture.length =
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 */
571 ) / 8
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;
592 if(include_extras) {
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);
612 free(picture.data.picture.description);
613 free(picture.data.picture.data);
614 if(!include_extras)
615 FLAC__metadata_object_delete(cuesheet);
617 return true;
620 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
622 const char *filename = flacfilename(is_ogg);
623 FLAC__StreamDecoder *decoder;
624 decoder_client_struct decoder_client_data;
626 FLAC__ASSERT(0 != metadata_callback);
628 mc_our_block_number_ = 0;
629 decoder_client_data.error_occurred = false;
631 printf("\ttesting '%s'... ", filename);
632 fflush(stdout);
634 if(0 == (decoder = FLAC__stream_decoder_new()))
635 return die_("couldn't allocate decoder instance");
637 FLAC__stream_decoder_set_md5_checking(decoder, true);
638 FLAC__stream_decoder_set_metadata_respond_all(decoder);
640 (is_ogg?
641 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
642 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
643 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
645 (void)FLAC__stream_decoder_finish(decoder);
646 FLAC__stream_decoder_delete(decoder);
647 return die_("initializing decoder\n");
649 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
650 (void)FLAC__stream_decoder_finish(decoder);
651 FLAC__stream_decoder_delete(decoder);
652 return die_("decoding file\n");
655 (void)FLAC__stream_decoder_finish(decoder);
656 FLAC__stream_decoder_delete(decoder);
658 if(decoder_client_data.error_occurred)
659 return false;
661 if(mc_our_block_number_ != our_metadata_.num_blocks)
662 return die_("short metadata block count");
664 printf("PASSED\n");
665 return true;
668 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
670 if(!grabbag__file_change_stats(filename, read_only))
671 return die_("during grabbag__file_change_stats()");
673 return true;
676 static FLAC__bool remove_file_(const char *filename)
678 while(our_metadata_.num_blocks > 0)
679 delete_from_our_metadata_(0);
681 if(!grabbag__file_remove_file(filename))
682 return die_("removing file");
684 return true;
687 static FLAC__bool test_level_0_(void)
689 FLAC__StreamMetadata streaminfo;
690 FLAC__StreamMetadata *tags = 0;
691 FLAC__StreamMetadata *cuesheet = 0;
692 FLAC__StreamMetadata *picture = 0;
694 printf("\n\n++++++ testing level 0 interface\n");
696 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
697 return false;
699 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
700 return false;
702 printf("testing FLAC__metadata_get_streaminfo()... ");
704 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
705 return die_("during FLAC__metadata_get_streaminfo()");
707 /* check to see if some basic data matches (c.f. generate_file_()) */
708 if(streaminfo.data.stream_info.channels != 1)
709 return die_("mismatch in streaminfo.data.stream_info.channels");
710 if(streaminfo.data.stream_info.bits_per_sample != 8)
711 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
712 if(streaminfo.data.stream_info.sample_rate != 44100)
713 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
714 if(streaminfo.data.stream_info.min_blocksize != 576)
715 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
716 if(streaminfo.data.stream_info.max_blocksize != 576)
717 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
719 printf("OK\n");
721 printf("testing FLAC__metadata_get_tags()... ");
723 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
724 return die_("during FLAC__metadata_get_tags()");
726 /* check to see if some basic data matches (c.f. generate_file_()) */
727 if(tags->data.vorbis_comment.num_comments != 0)
728 return die_("mismatch in tags->data.vorbis_comment.num_comments");
730 printf("OK\n");
732 FLAC__metadata_object_delete(tags);
734 printf("testing FLAC__metadata_get_cuesheet()... ");
736 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
737 return die_("during FLAC__metadata_get_cuesheet()");
739 /* check to see if some basic data matches (c.f. generate_file_()) */
740 if(cuesheet->data.cue_sheet.lead_in != 123)
741 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
743 printf("OK\n");
745 FLAC__metadata_object_delete(cuesheet);
747 printf("testing FLAC__metadata_get_picture()... ");
749 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)))
750 return die_("during FLAC__metadata_get_picture()");
752 /* check to see if some basic data matches (c.f. generate_file_()) */
753 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
754 return die_("mismatch in picture->data.picture.type");
756 printf("OK\n");
758 FLAC__metadata_object_delete(picture);
760 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
761 return false;
763 return true;
766 static FLAC__bool test_level_1_(void)
768 FLAC__Metadata_SimpleIterator *iterator;
769 FLAC__StreamMetadata *block, *app, *padding;
770 FLAC__byte data[1000];
771 unsigned our_current_position = 0;
773 /* initialize 'data' to avoid Valgrind errors */
774 memset(data, 0, sizeof(data));
776 printf("\n\n++++++ testing level 1 interface\n");
778 /************************************************************/
780 printf("simple iterator on read-only file\n");
782 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
783 return false;
785 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
786 return false;
788 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
789 return false;
791 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
792 return die_("FLAC__metadata_simple_iterator_new()");
794 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
795 return die_("FLAC__metadata_simple_iterator_init() returned false");
797 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
798 if(FLAC__metadata_simple_iterator_is_writable(iterator))
799 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
801 printf("iterate forwards\n");
803 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
804 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
805 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
806 return die_("getting block 0");
807 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
808 return die_("expected STREAMINFO type");
809 if(block->is_last)
810 return die_("expected is_last to be false");
811 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
812 return die_("bad STREAMINFO length");
813 /* check to see if some basic data matches (c.f. generate_file_()) */
814 if(block->data.stream_info.channels != 1)
815 return die_("mismatch in channels");
816 if(block->data.stream_info.bits_per_sample != 8)
817 return die_("mismatch in bits_per_sample");
818 if(block->data.stream_info.sample_rate != 44100)
819 return die_("mismatch in sample_rate");
820 if(block->data.stream_info.min_blocksize != 576)
821 return die_("mismatch in min_blocksize");
822 if(block->data.stream_info.max_blocksize != 576)
823 return die_("mismatch in max_blocksize");
824 FLAC__metadata_object_delete(block);
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_next(iterator))
831 return die_("forward iterator ended early");
832 our_current_position++;
834 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
835 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
836 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
837 return die_("getting block 2");
838 if(block->type != FLAC__METADATA_TYPE_PADDING)
839 return die_("expected PADDING type");
840 if(!block->is_last)
841 return die_("expected is_last to be true");
842 /* check to see if some basic data matches (c.f. generate_file_()) */
843 if(block->length != 1234)
844 return die_("bad PADDING length");
845 FLAC__metadata_object_delete(block);
847 if(FLAC__metadata_simple_iterator_next(iterator))
848 return die_("forward iterator returned true but should have returned false");
850 printf("iterate backwards\n");
851 if(!FLAC__metadata_simple_iterator_prev(iterator))
852 return die_("reverse iterator ended early");
853 if(!FLAC__metadata_simple_iterator_prev(iterator))
854 return die_("reverse iterator ended early");
855 if(FLAC__metadata_simple_iterator_prev(iterator))
856 return die_("reverse iterator returned true but should have returned false");
858 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
860 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
861 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
862 else
863 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
865 FLAC__metadata_simple_iterator_delete(iterator);
867 /************************************************************/
869 printf("simple iterator on writable file\n");
871 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
872 return false;
874 printf("creating APPLICATION block\n");
876 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
877 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
878 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
880 printf("creating PADDING block\n");
882 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
883 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
884 padding->length = 20;
886 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
887 return die_("FLAC__metadata_simple_iterator_new()");
889 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
890 return die_("FLAC__metadata_simple_iterator_init() returned false");
891 our_current_position = 0;
893 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
895 printf("[S]VP\ttry to write over STREAMINFO block...\n");
896 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
897 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
898 else
899 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
901 printf("[S]VP\tnext\n");
902 if(!FLAC__metadata_simple_iterator_next(iterator))
903 return die_("iterator ended early\n");
904 our_current_position++;
906 printf("S[V]P\tnext\n");
907 if(!FLAC__metadata_simple_iterator_next(iterator))
908 return die_("iterator ended early\n");
909 our_current_position++;
911 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
912 padding->length = 25;
913 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
914 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
915 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
916 return false;
918 printf("SVP[P]\tprev\n");
919 if(!FLAC__metadata_simple_iterator_prev(iterator))
920 return die_("iterator ended early\n");
921 our_current_position--;
923 printf("SV[P]P\tprev\n");
924 if(!FLAC__metadata_simple_iterator_prev(iterator))
925 return die_("iterator ended early\n");
926 our_current_position--;
928 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
929 padding->length = 30;
930 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
931 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
932 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
933 return false;
935 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
936 return false;
938 printf("SV[P]PP\tprev\n");
939 if(!FLAC__metadata_simple_iterator_prev(iterator))
940 return die_("iterator ended early\n");
941 our_current_position--;
943 printf("S[V]PPP\tprev\n");
944 if(!FLAC__metadata_simple_iterator_prev(iterator))
945 return die_("iterator ended early\n");
946 our_current_position--;
948 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
949 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
950 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
952 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
953 return false;
955 printf("[S]VPPP\tnext\n");
956 if(!FLAC__metadata_simple_iterator_next(iterator))
957 return die_("iterator ended early\n");
958 our_current_position++;
960 printf("S[V]PPP\tnext\n");
961 if(!FLAC__metadata_simple_iterator_next(iterator))
962 return die_("iterator ended early\n");
963 our_current_position++;
965 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
966 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
967 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
968 our_current_position--;
970 printf("S[V]PPP\tnext\n");
971 if(!FLAC__metadata_simple_iterator_next(iterator))
972 return die_("iterator ended early\n");
973 our_current_position++;
975 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
976 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
977 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
978 delete_from_our_metadata_(our_current_position--);
980 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
981 return false;
983 printf("S[V]PP\tnext\n");
984 if(!FLAC__metadata_simple_iterator_next(iterator))
985 return die_("iterator ended early\n");
986 our_current_position++;
988 printf("SV[P]P\tnext\n");
989 if(!FLAC__metadata_simple_iterator_next(iterator))
990 return die_("iterator ended early\n");
991 our_current_position++;
993 printf("SVP[P]\tdelete (last block), replace with padding\n");
994 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
995 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
996 our_current_position--;
998 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
999 return false;
1001 printf("SV[P]P\tnext\n");
1002 if(!FLAC__metadata_simple_iterator_next(iterator))
1003 return die_("iterator ended early\n");
1004 our_current_position++;
1006 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1007 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1008 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1009 delete_from_our_metadata_(our_current_position--);
1011 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1012 return false;
1014 printf("SV[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[V]P\tprev\n");
1020 if(!FLAC__metadata_simple_iterator_prev(iterator))
1021 return die_("iterator ended early\n");
1022 our_current_position--;
1024 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1025 FLAC__ASSERT(our_current_position == 0);
1026 block = FLAC__metadata_simple_iterator_get_block(iterator);
1027 block->data.stream_info.sample_rate = 32000;
1028 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1029 return die_("copying object");
1030 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1031 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1032 FLAC__metadata_object_delete(block);
1034 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1035 return false;
1037 printf("[S]VP\tnext\n");
1038 if(!FLAC__metadata_simple_iterator_next(iterator))
1039 return die_("iterator ended early\n");
1040 our_current_position++;
1042 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1043 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1044 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1045 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1046 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1047 return false;
1048 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1050 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1051 return false;
1053 printf("SV[A]P\tnext\n");
1054 if(!FLAC__metadata_simple_iterator_next(iterator))
1055 return die_("iterator ended early\n");
1056 our_current_position++;
1058 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1059 app->data.application.id[0] = 'f'; /* twiddle the id */
1060 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1061 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1062 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1063 return false;
1064 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1066 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1067 return false;
1069 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1070 app->data.application.id[0] = 'g'; /* twiddle the id */
1071 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1072 return die_("setting APPLICATION data");
1073 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1074 return die_("copying object");
1075 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1076 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1078 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1079 return false;
1081 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1082 app->data.application.id[0] = 'h'; /* twiddle the id */
1083 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1084 return die_("setting APPLICATION data");
1085 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1086 return die_("copying object");
1087 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1088 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1090 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1091 return false;
1093 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1094 app->data.application.id[0] = 'i'; /* twiddle the id */
1095 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1096 return die_("setting APPLICATION data");
1097 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1098 return die_("copying object");
1099 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1100 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1101 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1103 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1104 return false;
1106 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1107 app->data.application.id[0] = 'j'; /* twiddle the id */
1108 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1109 return die_("setting APPLICATION data");
1110 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1111 return die_("copying object");
1112 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1113 return die_("copying object");
1114 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1115 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1116 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1118 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1119 return false;
1121 printf("SVA[A]PP\tnext\n");
1122 if(!FLAC__metadata_simple_iterator_next(iterator))
1123 return die_("iterator ended early\n");
1124 our_current_position++;
1126 printf("SVAA[P]P\tnext\n");
1127 if(!FLAC__metadata_simple_iterator_next(iterator))
1128 return die_("iterator ended early\n");
1129 our_current_position++;
1131 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1132 padding->length = 5;
1133 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1134 return die_("copying object");
1135 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1136 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1138 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1139 return false;
1141 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1142 app->data.application.id[0] = 'k'; /* twiddle the id */
1143 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1144 return die_("copying object");
1145 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1146 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1148 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1149 return false;
1151 printf("SVAAP[A]\tset PADDING (equal)\n");
1152 padding->length = 27;
1153 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1154 return die_("copying object");
1155 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1156 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1158 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1159 return false;
1161 printf("SVAAP[P]\tprev\n");
1162 if(!FLAC__metadata_simple_iterator_prev(iterator))
1163 return die_("iterator ended early\n");
1164 our_current_position--;
1166 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1167 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1168 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1169 delete_from_our_metadata_(our_current_position--);
1171 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1172 return false;
1174 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1175 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1176 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1177 delete_from_our_metadata_(our_current_position--);
1179 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1180 return false;
1182 printf("SV[A]P\tnext\n");
1183 if(!FLAC__metadata_simple_iterator_next(iterator))
1184 return die_("iterator ended early\n");
1185 our_current_position++;
1187 printf("SVA[P]\tinsert PADDING after\n");
1188 padding->length = 5;
1189 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1190 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1191 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1192 return false;
1194 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1195 return false;
1197 printf("SVAP[P]\tprev\n");
1198 if(!FLAC__metadata_simple_iterator_prev(iterator))
1199 return die_("iterator ended early\n");
1200 our_current_position--;
1202 printf("SVA[P]P\tprev\n");
1203 if(!FLAC__metadata_simple_iterator_prev(iterator))
1204 return die_("iterator ended early\n");
1205 our_current_position--;
1207 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1208 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1209 return die_("setting APPLICATION data");
1210 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1211 return die_("copying object");
1212 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1213 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1215 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1216 return false;
1218 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1219 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1220 return die_("setting APPLICATION data");
1221 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1222 return die_("copying object");
1223 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1224 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1226 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1227 return false;
1229 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1230 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1231 return die_("setting APPLICATION data");
1232 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1233 return die_("copying object");
1234 our_metadata_.blocks[our_current_position+1]->length = 0;
1235 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1236 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1238 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1239 return false;
1241 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1242 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1243 return die_("setting APPLICATION data");
1244 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1245 return die_("copying object");
1246 delete_from_our_metadata_(our_current_position+1);
1247 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1248 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1250 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1251 return false;
1253 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1254 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1255 return die_("setting APPLICATION data");
1256 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1257 return die_("copying object");
1258 delete_from_our_metadata_(our_current_position+1);
1259 our_metadata_.blocks[our_current_position]->is_last = true;
1260 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1261 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1263 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1264 return false;
1266 printf("SV[A]\tset PADDING (equal size)\n");
1267 padding->length = app->length;
1268 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1269 return die_("copying object");
1270 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1271 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1273 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1274 return false;
1276 printf("SV[P]\tinsert PADDING after\n");
1277 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1278 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1279 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1280 return false;
1282 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1283 return false;
1285 printf("SVP[P]\tinsert PADDING after\n");
1286 padding->length = 5;
1287 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1288 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1289 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1290 return false;
1292 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1293 return false;
1295 printf("SVPP[P]\tprev\n");
1296 if(!FLAC__metadata_simple_iterator_prev(iterator))
1297 return die_("iterator ended early\n");
1298 our_current_position--;
1300 printf("SVP[P]P\tprev\n");
1301 if(!FLAC__metadata_simple_iterator_prev(iterator))
1302 return die_("iterator ended early\n");
1303 our_current_position--;
1305 printf("SV[P]PP\tprev\n");
1306 if(!FLAC__metadata_simple_iterator_prev(iterator))
1307 return die_("iterator ended early\n");
1308 our_current_position--;
1310 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1311 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1312 return die_("setting APPLICATION data");
1313 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1314 return die_("copying object");
1315 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1316 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1318 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1319 return false;
1321 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1322 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1323 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1324 delete_from_our_metadata_(our_current_position--);
1326 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1327 return false;
1329 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1330 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1331 return die_("setting APPLICATION data");
1332 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1333 return die_("copying object");
1334 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1335 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1337 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1338 return false;
1340 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1341 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1342 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1343 delete_from_our_metadata_(our_current_position--);
1345 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1346 return false;
1348 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1349 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1350 return die_("setting APPLICATION data");
1351 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1352 return die_("copying object");
1353 delete_from_our_metadata_(our_current_position+1);
1354 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1355 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1357 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1358 return false;
1360 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1361 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1362 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1363 delete_from_our_metadata_(our_current_position--);
1365 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1366 return false;
1368 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1369 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1370 return die_("setting APPLICATION data");
1371 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1372 return die_("copying object");
1373 our_metadata_.blocks[our_current_position+1]->length = 0;
1374 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1375 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1377 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1378 return false;
1380 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1381 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1382 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1383 delete_from_our_metadata_(our_current_position--);
1385 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1386 return false;
1388 printf("S[V]PP\tnext\n");
1389 if(!FLAC__metadata_simple_iterator_next(iterator))
1390 return die_("iterator ended early\n");
1391 our_current_position++;
1393 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1394 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1395 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1396 delete_from_our_metadata_(our_current_position--);
1398 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1399 return false;
1401 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1402 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1403 return die_("setting APPLICATION data");
1404 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1405 return die_("copying object");
1406 delete_from_our_metadata_(our_current_position+1);
1407 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1408 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1410 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1411 return false;
1413 printf("delete simple iterator\n");
1415 FLAC__metadata_simple_iterator_delete(iterator);
1417 FLAC__metadata_object_delete(app);
1418 FLAC__metadata_object_delete(padding);
1420 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1421 return false;
1423 return true;
1426 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1428 FLAC__Metadata_Iterator *iterator;
1429 FLAC__Metadata_Chain *chain;
1430 FLAC__StreamMetadata *block, *app, *padding;
1431 FLAC__byte data[2000];
1432 unsigned our_current_position;
1434 /* initialize 'data' to avoid Valgrind errors */
1435 memset(data, 0, sizeof(data));
1437 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1439 printf("generate read-only file\n");
1441 if(!generate_file_(/*include_extras=*/false, is_ogg))
1442 return false;
1444 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1445 return false;
1447 printf("create chain\n");
1449 if(0 == (chain = FLAC__metadata_chain_new()))
1450 return die_("allocating chain");
1452 printf("read chain\n");
1454 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1455 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1457 printf("[S]VP\ttest initial metadata\n");
1459 if(!compare_chain_(chain, 0, 0))
1460 return false;
1461 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1462 return false;
1464 if(is_ogg)
1465 goto end;
1467 printf("switch file to read-write\n");
1469 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1470 return false;
1472 printf("create iterator\n");
1473 if(0 == (iterator = FLAC__metadata_iterator_new()))
1474 return die_("allocating memory for iterator");
1476 our_current_position = 0;
1478 FLAC__metadata_iterator_init(iterator, chain);
1480 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1481 return die_("getting block from iterator");
1483 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1485 printf("[S]VP\tmodify STREAMINFO, write\n");
1487 block->data.stream_info.sample_rate = 32000;
1488 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1489 return die_("copying object");
1491 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1492 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1493 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1494 return false;
1495 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1496 return false;
1498 printf("[S]VP\tnext\n");
1499 if(!FLAC__metadata_iterator_next(iterator))
1500 return die_("iterator ended early\n");
1501 our_current_position++;
1503 printf("S[V]P\tnext\n");
1504 if(!FLAC__metadata_iterator_next(iterator))
1505 return die_("iterator ended early\n");
1506 our_current_position++;
1508 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1509 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1510 return die_("getting block from iterator");
1511 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1512 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1513 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1514 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1515 return die_("setting APPLICATION data");
1516 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1517 return die_("copying object");
1518 if(!FLAC__metadata_iterator_set_block(iterator, app))
1519 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1521 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1522 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1523 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1524 return false;
1525 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1526 return false;
1528 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1529 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1530 return die_("copying object");
1531 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1532 return die_("setting APPLICATION data");
1533 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1534 return die_("copying object");
1535 if(!FLAC__metadata_iterator_set_block(iterator, app))
1536 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1538 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1539 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1540 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1541 return false;
1542 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1543 return false;
1545 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1546 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1547 return die_("copying object");
1548 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1549 return die_("setting APPLICATION data");
1550 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1551 return die_("copying object");
1552 if(!FLAC__metadata_iterator_set_block(iterator, app))
1553 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1555 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1556 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1557 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1558 return false;
1559 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1560 return false;
1562 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1563 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1564 return die_("copying object");
1565 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1566 return die_("setting APPLICATION data");
1567 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1568 return die_("copying object");
1569 if(!FLAC__metadata_iterator_set_block(iterator, app))
1570 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1572 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1573 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1574 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1575 return false;
1576 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1577 return false;
1579 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1580 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1581 return die_("copying object");
1582 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1583 return die_("setting APPLICATION data");
1584 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1585 return die_("copying object");
1586 if(!FLAC__metadata_iterator_set_block(iterator, app))
1587 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1589 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1590 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1591 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1592 return false;
1593 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1594 return false;
1596 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1597 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1598 return die_("creating PADDING block");
1599 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1600 return die_("copying object");
1601 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1602 return die_("setting APPLICATION data");
1603 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1604 return die_("copying object");
1605 padding->length = 0;
1606 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1607 return die_("internal error");
1608 if(!FLAC__metadata_iterator_set_block(iterator, app))
1609 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1611 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1612 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1613 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1614 return false;
1615 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1616 return false;
1618 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1619 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1620 return die_("copying object");
1621 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1622 return die_("setting APPLICATION data");
1623 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1624 return die_("copying object");
1625 our_metadata_.blocks[our_current_position+1]->length = 13;
1626 if(!FLAC__metadata_iterator_set_block(iterator, app))
1627 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1629 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1630 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1631 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1632 return false;
1633 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1634 return false;
1636 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1637 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1638 return die_("copying object");
1639 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1640 return die_("setting APPLICATION data");
1641 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1642 return die_("copying object");
1643 if(!FLAC__metadata_iterator_set_block(iterator, app))
1644 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1646 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1647 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1648 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1649 return false;
1650 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1651 return false;
1653 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1654 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1655 return die_("copying object");
1656 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1657 return die_("setting APPLICATION data");
1658 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1659 return die_("copying object");
1660 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1661 if(!FLAC__metadata_iterator_set_block(iterator, app))
1662 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1664 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1665 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1666 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1667 return false;
1668 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1669 return false;
1671 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1672 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1673 return die_("copying object");
1674 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1675 return die_("setting APPLICATION data");
1676 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1677 return die_("copying object");
1678 delete_from_our_metadata_(our_current_position+1);
1679 if(!FLAC__metadata_iterator_set_block(iterator, app))
1680 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1682 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1683 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1684 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1685 return false;
1686 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1687 return false;
1689 printf("SV[A]\tprev\n");
1690 if(!FLAC__metadata_iterator_prev(iterator))
1691 return die_("iterator ended early\n");
1692 our_current_position--;
1694 printf("S[V]A\tprev\n");
1695 if(!FLAC__metadata_iterator_prev(iterator))
1696 return die_("iterator ended early\n");
1697 our_current_position--;
1699 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1700 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1701 return die_("creating PADDING block");
1702 padding->length = 30;
1703 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1704 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1705 else
1706 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1708 printf("[S]VP\tnext\n");
1709 if(!FLAC__metadata_iterator_next(iterator))
1710 return die_("iterator ended early\n");
1711 our_current_position++;
1713 printf("S[V]A\tinsert PADDING after\n");
1714 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1715 return die_("copying metadata");
1716 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1717 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1719 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1720 return false;
1722 printf("SV[P]A\tinsert PADDING before\n");
1723 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1724 return die_("creating PADDING block");
1725 padding->length = 17;
1726 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1727 return die_("copying metadata");
1728 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1729 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1731 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1732 return false;
1734 printf("SV[P]PA\tinsert PADDING before\n");
1735 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1736 return die_("creating PADDING block");
1737 padding->length = 0;
1738 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1739 return die_("copying metadata");
1740 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1741 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1743 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1744 return false;
1746 printf("SV[P]PPA\tnext\n");
1747 if(!FLAC__metadata_iterator_next(iterator))
1748 return die_("iterator ended early\n");
1749 our_current_position++;
1751 printf("SVP[P]PA\tnext\n");
1752 if(!FLAC__metadata_iterator_next(iterator))
1753 return die_("iterator ended early\n");
1754 our_current_position++;
1756 printf("SVPP[P]A\tnext\n");
1757 if(!FLAC__metadata_iterator_next(iterator))
1758 return die_("iterator ended early\n");
1759 our_current_position++;
1761 printf("SVPPP[A]\tinsert PADDING after\n");
1762 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1763 return die_("creating PADDING block");
1764 padding->length = 57;
1765 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1766 return die_("copying metadata");
1767 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1768 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1770 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1771 return false;
1773 printf("SVPPPA[P]\tinsert PADDING before\n");
1774 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1775 return die_("creating PADDING block");
1776 padding->length = 99;
1777 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1778 return die_("copying metadata");
1779 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1780 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1782 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1783 return false;
1785 printf("delete iterator\n");
1786 FLAC__metadata_iterator_delete(iterator);
1787 our_current_position = 0;
1789 printf("SVPPPAPP\tmerge padding\n");
1790 FLAC__metadata_chain_merge_padding(chain);
1791 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1792 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1793 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1794 delete_from_our_metadata_(7);
1795 delete_from_our_metadata_(4);
1796 delete_from_our_metadata_(3);
1798 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1799 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1800 if(!compare_chain_(chain, 0, 0))
1801 return false;
1802 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1803 return false;
1805 printf("SVPAP\tsort padding\n");
1806 FLAC__metadata_chain_sort_padding(chain);
1807 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1808 delete_from_our_metadata_(2);
1810 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1811 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1812 if(!compare_chain_(chain, 0, 0))
1813 return false;
1814 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1815 return false;
1817 printf("create iterator\n");
1818 if(0 == (iterator = FLAC__metadata_iterator_new()))
1819 return die_("allocating memory for iterator");
1821 our_current_position = 0;
1823 FLAC__metadata_iterator_init(iterator, chain);
1825 printf("[S]VAP\tnext\n");
1826 if(!FLAC__metadata_iterator_next(iterator))
1827 return die_("iterator ended early\n");
1828 our_current_position++;
1830 printf("S[V]AP\tnext\n");
1831 if(!FLAC__metadata_iterator_next(iterator))
1832 return die_("iterator ended early\n");
1833 our_current_position++;
1835 printf("SV[A]P\tdelete middle block, replace with padding\n");
1836 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1837 return die_("creating PADDING block");
1838 padding->length = 71;
1839 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1840 return die_("copying object");
1841 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1842 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1844 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1845 return false;
1847 printf("S[V]PP\tnext\n");
1848 if(!FLAC__metadata_iterator_next(iterator))
1849 return die_("iterator ended early\n");
1850 our_current_position++;
1852 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1853 delete_from_our_metadata_(our_current_position--);
1854 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1855 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1857 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1858 return false;
1860 printf("S[V]P\tnext\n");
1861 if(!FLAC__metadata_iterator_next(iterator))
1862 return die_("iterator ended early\n");
1863 our_current_position++;
1865 printf("SV[P]\tdelete last block, replace with padding\n");
1866 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1867 return die_("creating PADDING block");
1868 padding->length = 219;
1869 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1870 return die_("copying object");
1871 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1872 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1874 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1875 return false;
1877 printf("S[V]P\tnext\n");
1878 if(!FLAC__metadata_iterator_next(iterator))
1879 return die_("iterator ended early\n");
1880 our_current_position++;
1882 printf("SV[P]\tdelete last block, don't replace with padding\n");
1883 delete_from_our_metadata_(our_current_position--);
1884 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1885 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1887 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1888 return false;
1890 printf("S[V]\tprev\n");
1891 if(!FLAC__metadata_iterator_prev(iterator))
1892 return die_("iterator ended early\n");
1893 our_current_position--;
1895 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1896 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1897 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1899 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1900 return false;
1902 printf("delete iterator\n");
1903 FLAC__metadata_iterator_delete(iterator);
1904 our_current_position = 0;
1906 printf("SV\tmerge padding\n");
1907 FLAC__metadata_chain_merge_padding(chain);
1909 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1910 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1911 if(!compare_chain_(chain, 0, 0))
1912 return false;
1913 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1914 return false;
1916 printf("SV\tsort padding\n");
1917 FLAC__metadata_chain_sort_padding(chain);
1919 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1920 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1921 if(!compare_chain_(chain, 0, 0))
1922 return false;
1923 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1924 return false;
1926 end:
1927 printf("delete chain\n");
1929 FLAC__metadata_chain_delete(chain);
1931 if(!remove_file_(flacfilename(is_ogg)))
1932 return false;
1934 return true;
1937 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1939 FLAC__Metadata_Iterator *iterator;
1940 FLAC__Metadata_Chain *chain;
1941 FLAC__IOCallbacks callbacks;
1943 memset(&callbacks, 0, sizeof(callbacks));
1944 callbacks.read = (FLAC__IOCallback_Read)fread;
1945 #ifdef FLAC__VALGRIND_TESTING
1946 callbacks.write = chain_write_cb_;
1947 #else
1948 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1949 #endif
1950 callbacks.seek = chain_seek_cb_;
1951 callbacks.tell = chain_tell_cb_;
1952 callbacks.eof = chain_eof_cb_;
1954 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1956 printf("generate file\n");
1958 if(!generate_file_(/*include_extras=*/false, is_ogg))
1959 return false;
1961 printf("create chain\n");
1963 if(0 == (chain = FLAC__metadata_chain_new()))
1964 return die_("allocating chain");
1966 printf("read chain (filename-based)\n");
1968 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1969 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1971 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1973 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1974 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1975 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1976 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1977 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1980 printf("read chain (filename-based)\n");
1982 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1983 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1985 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1987 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1988 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1989 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1990 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1991 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1994 printf("read chain (callback-based)\n");
1996 FILE *file = fopen(flacfilename(is_ogg), "rb");
1997 if(0 == file)
1998 return die_("opening file");
1999 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2000 fclose(file);
2001 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2003 fclose(file);
2006 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2008 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2009 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2010 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2011 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2012 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2015 printf("read chain (callback-based)\n");
2017 FILE *file = fopen(flacfilename(is_ogg), "rb");
2018 if(0 == file)
2019 return die_("opening file");
2020 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2021 fclose(file);
2022 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2024 fclose(file);
2027 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2029 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2030 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2031 else
2032 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2034 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2036 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2037 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2038 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2039 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2040 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2043 printf("read chain (callback-based)\n");
2045 FILE *file = fopen(flacfilename(is_ogg), "rb");
2046 if(0 == file)
2047 return die_("opening file");
2048 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2049 fclose(file);
2050 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2052 fclose(file);
2055 printf("create iterator\n");
2056 if(0 == (iterator = FLAC__metadata_iterator_new()))
2057 return die_("allocating memory for iterator");
2059 FLAC__metadata_iterator_init(iterator, chain);
2061 printf("[S]VP\tnext\n");
2062 if(!FLAC__metadata_iterator_next(iterator))
2063 return die_("iterator ended early\n");
2065 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2066 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2067 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2069 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2071 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2072 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2073 else
2074 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2076 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2078 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2079 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2080 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2081 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2082 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2085 printf("delete iterator\n");
2087 FLAC__metadata_iterator_delete(iterator);
2089 printf("delete chain\n");
2091 FLAC__metadata_chain_delete(chain);
2093 if(!remove_file_(flacfilename(is_ogg)))
2094 return false;
2096 return true;
2099 FLAC__bool test_metadata_file_manipulation(void)
2101 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2103 our_metadata_.num_blocks = 0;
2105 if(!test_level_0_())
2106 return false;
2108 if(!test_level_1_())
2109 return false;
2111 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2112 return false;
2113 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2114 return false;
2115 if(!test_level_2_misc_(/*is_ogg=*/false))
2116 return false;
2118 if(FLAC_API_SUPPORTS_OGG_FLAC) {
2119 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2120 return false;
2121 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2122 return false;
2123 #if 0
2124 /* when ogg flac write is supported, will have to add this: */
2125 if(!test_level_2_misc_(/*is_ogg=*/true))
2126 return false;
2127 #endif
2130 return true;