Set version to 1.3.1pre1.
[flac.git] / src / test_libFLAC / metadata_manip.c
blob988ac71eee812e218a333d20ef15cda9277f5e4a
1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002-2009 Josh Coalson
3 * Copyright (C) 2011-2014 Xiph.Org Foundation
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h> /* for malloc() */
26 #include <string.h> /* for memcpy()/memset() */
27 #if defined _MSC_VER || defined __MINGW32__
28 #include <sys/utime.h> /* for utime() */
29 #include <io.h> /* for chmod() */
30 #else
31 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
32 #include <utime.h> /* for utime() */
33 #include <unistd.h> /* for chown(), unlink() */
34 #endif
35 #include <sys/stat.h> /* for stat(), maybe chmod() */
36 #include "FLAC/assert.h"
37 #include "FLAC/stream_decoder.h"
38 #include "FLAC/metadata.h"
39 #include "share/grabbag.h"
40 #include "share/compat.h"
41 #include "share/macros.h"
42 #include "share/safe_str.h"
43 #include "test_libs_common/file_utils_flac.h"
44 #include "test_libs_common/metadata_utils.h"
45 #include "metadata.h"
48 /******************************************************************************
49 The general strategy of these tests (for interface levels 1 and 2) is
50 to create a dummy FLAC file with a known set of initial metadata
51 blocks, then keep a mirror locally of what we expect the metadata to be
52 after each operation. Then testing becomes a simple matter of running
53 a FLAC__StreamDecoder over the dummy file after each operation, comparing
54 the decoded metadata to what's in our local copy. If there are any
55 differences in the metadata, or the actual audio data is corrupted, we
56 will catch it while decoding.
57 ******************************************************************************/
59 typedef struct {
60 FLAC__bool error_occurred;
61 } decoder_client_struct;
63 typedef struct {
64 FLAC__StreamMetadata *blocks[64];
65 unsigned num_blocks;
66 } our_metadata_struct;
68 /* our copy of the metadata in flacfilename() */
69 static our_metadata_struct our_metadata_;
71 /* the current block number that corresponds to the position of the iterator we are testing */
72 static unsigned mc_our_block_number_ = 0;
74 static const char *flacfilename(FLAC__bool is_ogg)
76 return is_ogg? "metadata.oga" : "metadata.flac";
79 static FLAC__bool die_(const char *msg)
81 printf("ERROR: %s\n", msg);
82 return false;
85 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
87 printf("ERROR: %s\n", msg);
88 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
89 return false;
92 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
94 printf("ERROR: %s\n", msg);
95 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
96 return false;
99 static void *malloc_or_die_(size_t size)
101 void *x = malloc(size);
102 if(0 == x) {
103 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
104 exit(1);
106 return x;
109 static char *strdup_or_die_(const char *s)
111 char *x = strdup(s);
112 if(0 == x) {
113 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
114 exit(1);
116 return x;
119 /* functions for working with our metadata copy */
121 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
123 unsigned i;
124 FLAC__StreamMetadata *obj = block;
125 FLAC__ASSERT(position < our_metadata_.num_blocks);
126 if(copy) {
127 if(0 == (obj = FLAC__metadata_object_clone(block)))
128 return die_("during FLAC__metadata_object_clone()");
130 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
131 our_metadata_.blocks[position] = obj;
133 /* set the is_last flags */
134 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
135 our_metadata_.blocks[i]->is_last = false;
136 our_metadata_.blocks[i]->is_last = true;
138 return true;
141 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
143 unsigned i;
144 FLAC__StreamMetadata *obj = block;
145 if(copy) {
146 if(0 == (obj = FLAC__metadata_object_clone(block)))
147 return die_("during FLAC__metadata_object_clone()");
149 if(position > our_metadata_.num_blocks) {
150 position = our_metadata_.num_blocks;
152 else {
153 for(i = our_metadata_.num_blocks; i > position; i--)
154 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
156 our_metadata_.blocks[position] = obj;
157 our_metadata_.num_blocks++;
159 /* set the is_last flags */
160 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
161 our_metadata_.blocks[i]->is_last = false;
162 our_metadata_.blocks[i]->is_last = true;
164 return true;
167 static void delete_from_our_metadata_(unsigned position)
169 unsigned i;
170 FLAC__ASSERT(position < our_metadata_.num_blocks);
171 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
172 for(i = position; i < our_metadata_.num_blocks - 1; i++)
173 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
174 our_metadata_.num_blocks--;
176 /* set the is_last flags */
177 if(our_metadata_.num_blocks > 0) {
178 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
179 our_metadata_.blocks[i]->is_last = false;
180 our_metadata_.blocks[i]->is_last = true;
185 * This wad of functions supports filename- and callback-based chain reading/writing.
186 * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
188 static FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
190 static const char *tempfile_suffix = ".metadata_edit";
191 size_t dest_len = strlen(filename) + strlen(tempfile_suffix) + 1;
192 if(0 == (*tempfilename = malloc(dest_len)))
193 return false;
194 safe_strncpy(*tempfilename, filename, dest_len);
195 safe_strncat(*tempfilename, tempfile_suffix, dest_len);
197 if(0 == (*tempfile = flac_fopen(*tempfilename, "wb")))
198 return false;
200 return true;
203 static void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
205 if(0 != *tempfile) {
206 (void)fclose(*tempfile);
207 *tempfile = 0;
210 if(0 != *tempfilename) {
211 (void)flac_unlink(*tempfilename);
212 free(*tempfilename);
213 *tempfilename = 0;
217 static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
219 FLAC__ASSERT(0 != filename);
220 FLAC__ASSERT(0 != tempfile);
221 FLAC__ASSERT(0 != tempfilename);
222 FLAC__ASSERT(0 != *tempfilename);
224 if(0 != *tempfile) {
225 (void)fclose(*tempfile);
226 *tempfile = 0;
229 #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
230 /* on some flavors of windows, flac_rename() will fail if the destination already exists */
231 if(flac_unlink(filename) < 0) {
232 cleanup_tempfile_(tempfile, tempfilename);
233 return false;
235 #endif
237 if(0 != flac_rename(*tempfilename, filename)) {
238 cleanup_tempfile_(tempfile, tempfilename);
239 return false;
242 cleanup_tempfile_(tempfile, tempfilename);
244 return true;
247 static FLAC__bool get_file_stats_(const char *filename, struct flac_stat_s *stats)
249 FLAC__ASSERT(0 != filename);
250 FLAC__ASSERT(0 != stats);
251 return (0 == flac_stat(filename, stats));
254 static void set_file_stats_(const char *filename, struct flac_stat_s *stats)
256 struct utimbuf srctime;
258 FLAC__ASSERT(0 != filename);
259 FLAC__ASSERT(0 != stats);
261 srctime.actime = stats->st_atime;
262 srctime.modtime = stats->st_mtime;
263 (void)flac_chmod(filename, stats->st_mode);
264 (void)flac_utime(filename, &srctime);
265 #if !defined _MSC_VER && !defined __MINGW32__
266 FLAC_CHECK_RETURN(chown(filename, stats->st_uid, -1));
267 FLAC_CHECK_RETURN(chown(filename, -1, stats->st_gid));
268 #endif
271 #ifdef FLAC__VALGRIND_TESTING
272 static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
274 FILE *stream = (FILE*)handle;
275 size_t ret = fwrite(ptr, size, nmemb, stream);
276 if(!ferror(stream))
277 fflush(stream);
278 return ret;
280 #endif
282 static int chain_seek_cb_(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
284 FLAC__off_t o = (FLAC__off_t)offset;
285 FLAC__ASSERT(offset == o);
286 return fseeko((FILE*)handle, o, whence);
289 static FLAC__int64 chain_tell_cb_(FLAC__IOHandle handle)
291 return ftello((FILE*)handle);
294 static int chain_eof_cb_(FLAC__IOHandle handle)
296 return feof((FILE*)handle);
299 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)
301 if(filename_based)
302 return FLAC__metadata_chain_write(chain, use_padding, preserve_file_stats);
303 else {
304 FLAC__IOCallbacks callbacks;
306 memset(&callbacks, 0, sizeof(callbacks));
307 callbacks.read = (FLAC__IOCallback_Read)fread;
308 #ifdef FLAC__VALGRIND_TESTING
309 callbacks.write = chain_write_cb_;
310 #else
311 callbacks.write = (FLAC__IOCallback_Write)fwrite;
312 #endif
313 callbacks.seek = chain_seek_cb_;
314 callbacks.eof = chain_eof_cb_;
316 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
317 struct flac_stat_s stats;
318 FILE *file, *tempfile = 0;
319 char *tempfilename;
320 if(preserve_file_stats) {
321 if(!get_file_stats_(filename, &stats))
322 return false;
324 if(0 == (file = flac_fopen(filename, "rb")))
325 return false; /*@@@@ chain status still says OK though */
326 if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
327 fclose(file);
328 cleanup_tempfile_(&tempfile, &tempfilename);
329 return false; /*@@@@ chain status still says OK though */
331 if(!FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, use_padding, (FLAC__IOHandle)file, callbacks, (FLAC__IOHandle)tempfile, callbacks)) {
332 fclose(file);
333 fclose(tempfile);
334 return false;
336 fclose(file);
337 fclose(tempfile);
338 file = tempfile = 0;
339 if(!transport_tempfile_(filename, &tempfile, &tempfilename))
340 return false;
341 if(preserve_file_stats)
342 set_file_stats_(filename, &stats);
344 else {
345 FILE *file = flac_fopen(filename, "r+b");
346 if(0 == file)
347 return false; /*@@@@ chain status still says OK though */
348 if(!FLAC__metadata_chain_write_with_callbacks(chain, use_padding, (FLAC__IOHandle)file, callbacks))
349 return false;
350 fclose(file);
354 return true;
357 static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based, FLAC__bool is_ogg)
359 if(filename_based)
360 return is_ogg?
361 FLAC__metadata_chain_read_ogg(chain, flacfilename(is_ogg)) :
362 FLAC__metadata_chain_read(chain, flacfilename(is_ogg))
364 else {
365 FLAC__IOCallbacks callbacks;
367 memset(&callbacks, 0, sizeof(callbacks));
368 callbacks.read = (FLAC__IOCallback_Read)fread;
369 callbacks.seek = chain_seek_cb_;
370 callbacks.tell = chain_tell_cb_;
373 FLAC__bool ret;
374 FILE *file = flac_fopen(filename, "rb");
375 if(0 == file)
376 return false; /*@@@@ chain status still says OK though */
377 ret = is_ogg?
378 FLAC__metadata_chain_read_ogg_with_callbacks(chain, (FLAC__IOHandle)file, callbacks) :
379 FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)
381 fclose(file);
382 return ret;
387 /* function for comparing our metadata to a FLAC__Metadata_Chain */
389 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
391 unsigned i;
392 FLAC__Metadata_Iterator *iterator;
393 FLAC__StreamMetadata *block;
394 FLAC__bool next_ok = true;
396 FLAC__ASSERT(0 != chain);
398 printf("\tcomparing chain... ");
399 fflush(stdout);
401 if(0 == (iterator = FLAC__metadata_iterator_new()))
402 return die_("allocating memory for iterator");
404 FLAC__metadata_iterator_init(iterator, chain);
406 i = 0;
407 do {
408 printf("%u... ", i);
409 fflush(stdout);
411 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
412 FLAC__metadata_iterator_delete(iterator);
413 return die_("getting block from iterator");
416 if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
417 FLAC__metadata_iterator_delete(iterator);
418 return die_("metadata block mismatch");
421 i++;
422 next_ok = FLAC__metadata_iterator_next(iterator);
423 } while(i < our_metadata_.num_blocks && next_ok);
425 FLAC__metadata_iterator_delete(iterator);
427 if(next_ok)
428 return die_("chain has more blocks than expected");
430 if(i < our_metadata_.num_blocks)
431 return die_("short block count in chain");
433 if(0 != current_block) {
434 printf("CURRENT_POSITION... ");
435 fflush(stdout);
437 if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
438 return die_("metadata block mismatch");
441 printf("PASSED\n");
443 return true;
446 /* decoder callbacks for checking the file */
448 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
450 (void)decoder, (void)buffer, (void)client_data;
453 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
454 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
456 printf("content... ");
457 fflush(stdout);
460 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
463 /* this version pays no attention to the metadata */
464 static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
466 (void)decoder, (void)metadata, (void)client_data;
468 printf("%d... ", mc_our_block_number_);
469 fflush(stdout);
471 mc_our_block_number_++;
474 /* this version is used when we want to compare to our metadata copy */
475 static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
477 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
479 (void)decoder;
481 /* don't bother checking if we've already hit an error */
482 if(dcd->error_occurred)
483 return;
485 printf("%d... ", mc_our_block_number_);
486 fflush(stdout);
488 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
489 (void)die_("got more metadata blocks than expected");
490 dcd->error_occurred = true;
492 else {
493 if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
494 (void)die_("metadata block mismatch");
495 dcd->error_occurred = true;
498 mc_our_block_number_++;
501 static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
503 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
504 (void)decoder;
506 dcd->error_occurred = true;
507 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
510 static FLAC__bool generate_file_(FLAC__bool include_extras, FLAC__bool is_ogg)
512 FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
513 FLAC__StreamMetadata *metadata[4];
514 unsigned i = 0, n = 0;
516 printf("generating %sFLAC file for test\n", is_ogg? "Ogg " : "");
518 while(our_metadata_.num_blocks > 0)
519 delete_from_our_metadata_(0);
521 streaminfo.is_last = false;
522 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
523 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
524 streaminfo.data.stream_info.min_blocksize = 576;
525 streaminfo.data.stream_info.max_blocksize = 576;
526 streaminfo.data.stream_info.min_framesize = 0;
527 streaminfo.data.stream_info.max_framesize = 0;
528 streaminfo.data.stream_info.sample_rate = 44100;
529 streaminfo.data.stream_info.channels = 1;
530 streaminfo.data.stream_info.bits_per_sample = 8;
531 streaminfo.data.stream_info.total_samples = 0;
532 memset(streaminfo.data.stream_info.md5sum, 0, 16);
535 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
536 vorbiscomment.is_last = false;
537 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
538 vorbiscomment.length = (4 + vendor_string_length) + 4;
539 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
540 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
541 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
542 vorbiscomment.data.vorbis_comment.num_comments = 0;
543 vorbiscomment.data.vorbis_comment.comments = 0;
547 if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
548 return die_("priming our metadata");
549 cuesheet->is_last = false;
550 safe_strncpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN", sizeof(cuesheet->data.cue_sheet.media_catalog_number));
551 cuesheet->data.cue_sheet.lead_in = 123;
552 cuesheet->data.cue_sheet.is_cd = false;
553 if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
554 return die_("priming our metadata");
555 cuesheet->data.cue_sheet.tracks[0].number = 1;
556 if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
557 return die_("priming our metadata");
561 picture.is_last = false;
562 picture.type = FLAC__METADATA_TYPE_PICTURE;
563 picture.length =
565 FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
566 FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
567 FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
568 FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
569 FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
570 FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
571 FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
572 FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
573 ) / 8
575 picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
576 picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
577 picture.length += strlen(picture.data.picture.mime_type);
578 picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
579 picture.length += strlen((const char *)picture.data.picture.description);
580 picture.data.picture.width = 300;
581 picture.data.picture.height = 300;
582 picture.data.picture.depth = 24;
583 picture.data.picture.colors = 0;
584 picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
585 picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
586 picture.length += picture.data.picture.data_length;
589 padding.is_last = true;
590 padding.type = FLAC__METADATA_TYPE_PADDING;
591 padding.length = 1234;
593 metadata[n++] = &vorbiscomment;
594 if(include_extras) {
595 metadata[n++] = cuesheet;
596 metadata[n++] = &picture;
598 metadata[n++] = &padding;
601 !insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
602 !insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
603 (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
604 (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
605 !insert_to_our_metadata_(&padding, i++, /*copy=*/true)
607 return die_("priming our metadata");
609 if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), 0, 512 * 1024, &streaminfo, metadata, n))
610 return die_("creating the encoded file");
612 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
613 free(picture.data.picture.mime_type);
614 free(picture.data.picture.description);
615 free(picture.data.picture.data);
616 if(!include_extras)
617 FLAC__metadata_object_delete(cuesheet);
619 return true;
622 static FLAC__bool test_file_(FLAC__bool is_ogg, FLAC__StreamDecoderMetadataCallback metadata_callback)
624 const char *filename = flacfilename(is_ogg);
625 FLAC__StreamDecoder *decoder;
626 decoder_client_struct decoder_client_data;
628 FLAC__ASSERT(0 != metadata_callback);
630 mc_our_block_number_ = 0;
631 decoder_client_data.error_occurred = false;
633 printf("\ttesting '%s'... ", filename);
634 fflush(stdout);
636 if(0 == (decoder = FLAC__stream_decoder_new()))
637 return die_("couldn't allocate decoder instance");
639 FLAC__stream_decoder_set_md5_checking(decoder, true);
640 FLAC__stream_decoder_set_metadata_respond_all(decoder);
642 (is_ogg?
643 FLAC__stream_decoder_init_ogg_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) :
644 FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data)
645 ) != FLAC__STREAM_DECODER_INIT_STATUS_OK
647 (void)FLAC__stream_decoder_finish(decoder);
648 FLAC__stream_decoder_delete(decoder);
649 return die_("initializing decoder\n");
651 if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
652 (void)FLAC__stream_decoder_finish(decoder);
653 FLAC__stream_decoder_delete(decoder);
654 return die_("decoding file\n");
657 (void)FLAC__stream_decoder_finish(decoder);
658 FLAC__stream_decoder_delete(decoder);
660 if(decoder_client_data.error_occurred)
661 return false;
663 if(mc_our_block_number_ != our_metadata_.num_blocks)
664 return die_("short metadata block count");
666 printf("PASSED\n");
667 return true;
670 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
672 if(!grabbag__file_change_stats(filename, read_only))
673 return die_("during grabbag__file_change_stats()");
675 return true;
678 static FLAC__bool remove_file_(const char *filename)
680 while(our_metadata_.num_blocks > 0)
681 delete_from_our_metadata_(0);
683 if(!grabbag__file_remove_file(filename))
684 return die_("removing file");
686 return true;
689 static FLAC__bool test_level_0_(void)
691 FLAC__StreamMetadata streaminfo;
692 FLAC__StreamMetadata *tags = 0;
693 FLAC__StreamMetadata *cuesheet = 0;
694 FLAC__StreamMetadata *picture = 0;
696 printf("\n\n++++++ testing level 0 interface\n");
698 if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
699 return false;
701 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
702 return false;
704 printf("testing FLAC__metadata_get_streaminfo()... ");
706 if(!FLAC__metadata_get_streaminfo(flacfilename(/*is_ogg=*/false), &streaminfo))
707 return die_("during FLAC__metadata_get_streaminfo()");
709 /* check to see if some basic data matches (c.f. generate_file_()) */
710 if(streaminfo.data.stream_info.channels != 1)
711 return die_("mismatch in streaminfo.data.stream_info.channels");
712 if(streaminfo.data.stream_info.bits_per_sample != 8)
713 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
714 if(streaminfo.data.stream_info.sample_rate != 44100)
715 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
716 if(streaminfo.data.stream_info.min_blocksize != 576)
717 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
718 if(streaminfo.data.stream_info.max_blocksize != 576)
719 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
721 printf("OK\n");
723 printf("testing FLAC__metadata_get_tags()... ");
725 if(!FLAC__metadata_get_tags(flacfilename(/*is_ogg=*/false), &tags))
726 return die_("during FLAC__metadata_get_tags()");
728 /* check to see if some basic data matches (c.f. generate_file_()) */
729 if(tags->data.vorbis_comment.num_comments != 0)
730 return die_("mismatch in tags->data.vorbis_comment.num_comments");
732 printf("OK\n");
734 FLAC__metadata_object_delete(tags);
736 printf("testing FLAC__metadata_get_cuesheet()... ");
738 if(!FLAC__metadata_get_cuesheet(flacfilename(/*is_ogg=*/false), &cuesheet))
739 return die_("during FLAC__metadata_get_cuesheet()");
741 /* check to see if some basic data matches (c.f. generate_file_()) */
742 if(cuesheet->data.cue_sheet.lead_in != 123)
743 return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
745 printf("OK\n");
747 FLAC__metadata_object_delete(cuesheet);
749 printf("testing FLAC__metadata_get_picture()... ");
751 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)))
752 return die_("during FLAC__metadata_get_picture()");
754 /* check to see if some basic data matches (c.f. generate_file_()) */
755 if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
756 return die_("mismatch in picture->data.picture.type");
758 printf("OK\n");
760 FLAC__metadata_object_delete(picture);
762 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
763 return false;
765 return true;
768 static FLAC__bool test_level_1_(void)
770 FLAC__Metadata_SimpleIterator *iterator;
771 FLAC__StreamMetadata *block, *app, *padding;
772 FLAC__byte data[1000];
773 unsigned our_current_position = 0;
775 /* initialize 'data' to avoid Valgrind errors */
776 memset(data, 0, sizeof(data));
778 printf("\n\n++++++ testing level 1 interface\n");
780 /************************************************************/
782 printf("simple iterator on read-only file\n");
784 if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
785 return false;
787 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
788 return false;
790 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_null_))
791 return false;
793 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
794 return die_("FLAC__metadata_simple_iterator_new()");
796 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
797 return die_("FLAC__metadata_simple_iterator_init() returned false");
799 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
800 if(FLAC__metadata_simple_iterator_is_writable(iterator))
801 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
803 printf("iterate forwards\n");
805 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
806 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
807 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
808 return die_("getting block 0");
809 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
810 return die_("expected STREAMINFO type");
811 if(block->is_last)
812 return die_("expected is_last to be false");
813 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
814 return die_("bad STREAMINFO length");
815 /* check to see if some basic data matches (c.f. generate_file_()) */
816 if(block->data.stream_info.channels != 1)
817 return die_("mismatch in channels");
818 if(block->data.stream_info.bits_per_sample != 8)
819 return die_("mismatch in bits_per_sample");
820 if(block->data.stream_info.sample_rate != 44100)
821 return die_("mismatch in sample_rate");
822 if(block->data.stream_info.min_blocksize != 576)
823 return die_("mismatch in min_blocksize");
824 if(block->data.stream_info.max_blocksize != 576)
825 return die_("mismatch in max_blocksize");
826 FLAC__metadata_object_delete(block);
828 if(!FLAC__metadata_simple_iterator_next(iterator))
829 return die_("forward iterator ended early");
830 our_current_position++;
832 if(!FLAC__metadata_simple_iterator_next(iterator))
833 return die_("forward iterator ended early");
834 our_current_position++;
836 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
837 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
838 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
839 return die_("getting block 2");
840 if(block->type != FLAC__METADATA_TYPE_PADDING)
841 return die_("expected PADDING type");
842 if(!block->is_last)
843 return die_("expected is_last to be true");
844 /* check to see if some basic data matches (c.f. generate_file_()) */
845 if(block->length != 1234)
846 return die_("bad PADDING length");
847 FLAC__metadata_object_delete(block);
849 if(FLAC__metadata_simple_iterator_next(iterator))
850 return die_("forward iterator returned true but should have returned false");
852 printf("iterate backwards\n");
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 ended early");
857 if(FLAC__metadata_simple_iterator_prev(iterator))
858 return die_("reverse iterator returned true but should have returned false");
860 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
862 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
863 printf("OK: FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
864 else
865 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
867 FLAC__metadata_simple_iterator_delete(iterator);
869 /************************************************************/
871 printf("simple iterator on writable file\n");
873 if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
874 return false;
876 printf("creating APPLICATION block\n");
878 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
879 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
880 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
882 printf("creating PADDING block\n");
884 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
885 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
886 padding->length = 20;
888 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
889 return die_("FLAC__metadata_simple_iterator_new()");
891 if(!FLAC__metadata_simple_iterator_init(iterator, flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
892 return die_("FLAC__metadata_simple_iterator_init() returned false");
893 our_current_position = 0;
895 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
897 printf("[S]VP\ttry to write over STREAMINFO block...\n");
898 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
899 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
900 else
901 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
903 printf("[S]VP\tnext\n");
904 if(!FLAC__metadata_simple_iterator_next(iterator))
905 return die_("iterator ended early\n");
906 our_current_position++;
908 printf("S[V]P\tnext\n");
909 if(!FLAC__metadata_simple_iterator_next(iterator))
910 return die_("iterator ended early\n");
911 our_current_position++;
913 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
914 padding->length = 25;
915 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
916 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
917 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
918 return false;
920 printf("SVP[P]\tprev\n");
921 if(!FLAC__metadata_simple_iterator_prev(iterator))
922 return die_("iterator ended early\n");
923 our_current_position--;
925 printf("SV[P]P\tprev\n");
926 if(!FLAC__metadata_simple_iterator_prev(iterator))
927 return die_("iterator ended early\n");
928 our_current_position--;
930 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
931 padding->length = 30;
932 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
933 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
934 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
935 return false;
937 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
938 return false;
940 printf("SV[P]PP\tprev\n");
941 if(!FLAC__metadata_simple_iterator_prev(iterator))
942 return die_("iterator ended early\n");
943 our_current_position--;
945 printf("S[V]PPP\tprev\n");
946 if(!FLAC__metadata_simple_iterator_prev(iterator))
947 return die_("iterator ended early\n");
948 our_current_position--;
950 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
951 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
952 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
954 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
955 return false;
957 printf("[S]VPPP\tnext\n");
958 if(!FLAC__metadata_simple_iterator_next(iterator))
959 return die_("iterator ended early\n");
960 our_current_position++;
962 printf("S[V]PPP\tnext\n");
963 if(!FLAC__metadata_simple_iterator_next(iterator))
964 return die_("iterator ended early\n");
965 our_current_position++;
967 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
968 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
969 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
970 our_current_position--;
972 printf("S[V]PPP\tnext\n");
973 if(!FLAC__metadata_simple_iterator_next(iterator))
974 return die_("iterator ended early\n");
975 our_current_position++;
977 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
978 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
979 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
980 delete_from_our_metadata_(our_current_position--);
982 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
983 return false;
985 printf("S[V]PP\tnext\n");
986 if(!FLAC__metadata_simple_iterator_next(iterator))
987 return die_("iterator ended early\n");
988 our_current_position++;
990 printf("SV[P]P\tnext\n");
991 if(!FLAC__metadata_simple_iterator_next(iterator))
992 return die_("iterator ended early\n");
993 our_current_position++;
995 printf("SVP[P]\tdelete (last block), replace with padding\n");
996 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
997 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
998 our_current_position--;
1000 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1001 return false;
1003 printf("SV[P]P\tnext\n");
1004 if(!FLAC__metadata_simple_iterator_next(iterator))
1005 return die_("iterator ended early\n");
1006 our_current_position++;
1008 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1009 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1010 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1011 delete_from_our_metadata_(our_current_position--);
1013 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1014 return false;
1016 printf("SV[P]\tprev\n");
1017 if(!FLAC__metadata_simple_iterator_prev(iterator))
1018 return die_("iterator ended early\n");
1019 our_current_position--;
1021 printf("S[V]P\tprev\n");
1022 if(!FLAC__metadata_simple_iterator_prev(iterator))
1023 return die_("iterator ended early\n");
1024 our_current_position--;
1026 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1027 FLAC__ASSERT(our_current_position == 0);
1028 block = FLAC__metadata_simple_iterator_get_block(iterator);
1029 block->data.stream_info.sample_rate = 32000;
1030 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1031 return die_("copying object");
1032 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
1033 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
1034 FLAC__metadata_object_delete(block);
1036 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1037 return false;
1039 printf("[S]VP\tnext\n");
1040 if(!FLAC__metadata_simple_iterator_next(iterator))
1041 return die_("iterator ended early\n");
1042 our_current_position++;
1044 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1045 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
1046 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1047 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1048 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1049 return false;
1050 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1052 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1053 return false;
1055 printf("SV[A]P\tnext\n");
1056 if(!FLAC__metadata_simple_iterator_next(iterator))
1057 return die_("iterator ended early\n");
1058 our_current_position++;
1060 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1061 app->data.application.id[0] = 'f'; /* twiddle the id */
1062 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1063 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1064 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1065 return false;
1066 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
1068 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1069 return false;
1071 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1072 app->data.application.id[0] = 'g'; /* twiddle the id */
1073 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1074 return die_("setting APPLICATION data");
1075 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1076 return die_("copying object");
1077 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1078 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1080 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1081 return false;
1083 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1084 app->data.application.id[0] = 'h'; /* twiddle the id */
1085 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
1086 return die_("setting APPLICATION data");
1087 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1088 return die_("copying object");
1089 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1090 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1092 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1093 return false;
1095 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1096 app->data.application.id[0] = 'i'; /* twiddle the id */
1097 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
1098 return die_("setting APPLICATION data");
1099 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1100 return die_("copying object");
1101 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
1102 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1103 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1105 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1106 return false;
1108 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1109 app->data.application.id[0] = 'j'; /* twiddle the id */
1110 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
1111 return die_("setting APPLICATION data");
1112 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1113 return die_("copying object");
1114 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1115 return die_("copying object");
1116 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
1117 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1118 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1120 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1121 return false;
1123 printf("SVA[A]PP\tnext\n");
1124 if(!FLAC__metadata_simple_iterator_next(iterator))
1125 return die_("iterator ended early\n");
1126 our_current_position++;
1128 printf("SVAA[P]P\tnext\n");
1129 if(!FLAC__metadata_simple_iterator_next(iterator))
1130 return die_("iterator ended early\n");
1131 our_current_position++;
1133 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1134 padding->length = 5;
1135 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1136 return die_("copying object");
1137 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1138 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1140 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1141 return false;
1143 printf("SVAAP[P]\tset APPLICATION (grow)\n");
1144 app->data.application.id[0] = 'k'; /* twiddle the id */
1145 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1146 return die_("copying object");
1147 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
1148 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
1150 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1151 return false;
1153 printf("SVAAP[A]\tset PADDING (equal)\n");
1154 padding->length = 27;
1155 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1156 return die_("copying object");
1157 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
1158 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
1160 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1161 return false;
1163 printf("SVAAP[P]\tprev\n");
1164 if(!FLAC__metadata_simple_iterator_prev(iterator))
1165 return die_("iterator ended early\n");
1166 our_current_position--;
1168 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1169 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1170 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1171 delete_from_our_metadata_(our_current_position--);
1173 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1174 return false;
1176 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1177 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1178 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1179 delete_from_our_metadata_(our_current_position--);
1181 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1182 return false;
1184 printf("SV[A]P\tnext\n");
1185 if(!FLAC__metadata_simple_iterator_next(iterator))
1186 return die_("iterator ended early\n");
1187 our_current_position++;
1189 printf("SVA[P]\tinsert PADDING after\n");
1190 padding->length = 5;
1191 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1192 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1193 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1194 return false;
1196 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1197 return false;
1199 printf("SVAP[P]\tprev\n");
1200 if(!FLAC__metadata_simple_iterator_prev(iterator))
1201 return die_("iterator ended early\n");
1202 our_current_position--;
1204 printf("SVA[P]P\tprev\n");
1205 if(!FLAC__metadata_simple_iterator_prev(iterator))
1206 return die_("iterator ended early\n");
1207 our_current_position--;
1209 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1210 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
1211 return die_("setting APPLICATION data");
1212 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1213 return die_("copying object");
1214 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1215 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1217 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1218 return false;
1220 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1221 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
1222 return die_("setting APPLICATION data");
1223 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1224 return die_("copying object");
1225 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1226 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1228 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1229 return false;
1231 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1232 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
1233 return die_("setting APPLICATION data");
1234 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1235 return die_("copying object");
1236 our_metadata_.blocks[our_current_position+1]->length = 0;
1237 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1238 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1240 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1241 return false;
1243 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1244 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
1245 return die_("setting APPLICATION data");
1246 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1247 return die_("copying object");
1248 delete_from_our_metadata_(our_current_position+1);
1249 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1250 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1252 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1253 return false;
1255 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1256 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1257 return die_("setting APPLICATION data");
1258 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1259 return die_("copying object");
1260 delete_from_our_metadata_(our_current_position+1);
1261 our_metadata_.blocks[our_current_position]->is_last = true;
1262 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
1263 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
1265 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1266 return false;
1268 printf("SV[A]\tset PADDING (equal size)\n");
1269 padding->length = app->length;
1270 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1271 return die_("copying object");
1272 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
1273 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
1275 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1276 return false;
1278 printf("SV[P]\tinsert PADDING after\n");
1279 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1280 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1281 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1282 return false;
1284 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1285 return false;
1287 printf("SVP[P]\tinsert PADDING after\n");
1288 padding->length = 5;
1289 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
1290 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
1291 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1292 return false;
1294 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1295 return false;
1297 printf("SVPP[P]\tprev\n");
1298 if(!FLAC__metadata_simple_iterator_prev(iterator))
1299 return die_("iterator ended early\n");
1300 our_current_position--;
1302 printf("SVP[P]P\tprev\n");
1303 if(!FLAC__metadata_simple_iterator_prev(iterator))
1304 return die_("iterator ended early\n");
1305 our_current_position--;
1307 printf("SV[P]PP\tprev\n");
1308 if(!FLAC__metadata_simple_iterator_prev(iterator))
1309 return die_("iterator ended early\n");
1310 our_current_position--;
1312 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1313 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
1314 return die_("setting APPLICATION data");
1315 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1316 return die_("copying object");
1317 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1318 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1320 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1321 return false;
1323 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1324 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1325 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1326 delete_from_our_metadata_(our_current_position--);
1328 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1329 return false;
1331 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1332 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
1333 return die_("setting APPLICATION data");
1334 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1335 return die_("copying object");
1336 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1337 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1339 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1340 return false;
1342 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1343 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1344 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1345 delete_from_our_metadata_(our_current_position--);
1347 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1348 return false;
1350 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1351 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1352 return die_("setting APPLICATION data");
1353 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1354 return die_("copying object");
1355 delete_from_our_metadata_(our_current_position+1);
1356 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1357 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1359 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1360 return false;
1362 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1363 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1364 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1365 delete_from_our_metadata_(our_current_position--);
1367 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1368 return false;
1370 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1371 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1372 return die_("setting APPLICATION data");
1373 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1374 return die_("copying object");
1375 our_metadata_.blocks[our_current_position+1]->length = 0;
1376 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1377 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1379 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1380 return false;
1382 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1383 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1384 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1385 delete_from_our_metadata_(our_current_position--);
1387 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1388 return false;
1390 printf("S[V]PP\tnext\n");
1391 if(!FLAC__metadata_simple_iterator_next(iterator))
1392 return die_("iterator ended early\n");
1393 our_current_position++;
1395 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1396 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1397 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1398 delete_from_our_metadata_(our_current_position--);
1400 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1401 return false;
1403 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1404 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1405 return die_("setting APPLICATION data");
1406 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1407 return die_("copying object");
1408 delete_from_our_metadata_(our_current_position+1);
1409 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1410 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1412 if(!test_file_(/*is_ogg=*/false, decoder_metadata_callback_compare_))
1413 return false;
1415 printf("delete simple iterator\n");
1417 FLAC__metadata_simple_iterator_delete(iterator);
1419 FLAC__metadata_object_delete(app);
1420 FLAC__metadata_object_delete(padding);
1422 if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1423 return false;
1425 return true;
1428 static FLAC__bool test_level_2_(FLAC__bool filename_based, FLAC__bool is_ogg)
1430 FLAC__Metadata_Iterator *iterator;
1431 FLAC__Metadata_Chain *chain;
1432 FLAC__StreamMetadata *block, *app, *padding;
1433 FLAC__byte data[2000];
1434 unsigned our_current_position;
1436 /* initialize 'data' to avoid Valgrind errors */
1437 memset(data, 0, sizeof(data));
1439 printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1441 printf("generate read-only file\n");
1443 if(!generate_file_(/*include_extras=*/false, is_ogg))
1444 return false;
1446 if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1447 return false;
1449 printf("create chain\n");
1451 if(0 == (chain = FLAC__metadata_chain_new()))
1452 return die_("allocating chain");
1454 printf("read chain\n");
1456 if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1457 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1459 printf("[S]VP\ttest initial metadata\n");
1461 if(!compare_chain_(chain, 0, 0))
1462 return false;
1463 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1464 return false;
1466 if(is_ogg)
1467 goto end;
1469 printf("switch file to read-write\n");
1471 if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1472 return false;
1474 printf("create iterator\n");
1475 if(0 == (iterator = FLAC__metadata_iterator_new()))
1476 return die_("allocating memory for iterator");
1478 our_current_position = 0;
1480 FLAC__metadata_iterator_init(iterator, chain);
1482 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1483 return die_("getting block from iterator");
1485 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1487 printf("[S]VP\tmodify STREAMINFO, write\n");
1489 block->data.stream_info.sample_rate = 32000;
1490 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1491 return die_("copying object");
1493 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1494 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1495 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1496 return false;
1497 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1498 return false;
1500 printf("[S]VP\tnext\n");
1501 if(!FLAC__metadata_iterator_next(iterator))
1502 return die_("iterator ended early\n");
1503 our_current_position++;
1505 printf("S[V]P\tnext\n");
1506 if(!FLAC__metadata_iterator_next(iterator))
1507 return die_("iterator ended early\n");
1508 our_current_position++;
1510 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1511 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1512 return die_("getting block from iterator");
1513 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1514 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1515 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1516 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1517 return die_("setting APPLICATION data");
1518 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1519 return die_("copying object");
1520 if(!FLAC__metadata_iterator_set_block(iterator, app))
1521 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1523 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1524 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1525 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1526 return false;
1527 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1528 return false;
1530 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1531 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1532 return die_("copying object");
1533 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1534 return die_("setting APPLICATION data");
1535 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1536 return die_("copying object");
1537 if(!FLAC__metadata_iterator_set_block(iterator, app))
1538 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1540 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1541 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1542 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1543 return false;
1544 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1545 return false;
1547 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1548 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1549 return die_("copying object");
1550 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1551 return die_("setting APPLICATION data");
1552 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1553 return die_("copying object");
1554 if(!FLAC__metadata_iterator_set_block(iterator, app))
1555 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1557 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1558 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1559 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1560 return false;
1561 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1562 return false;
1564 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1565 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1566 return die_("copying object");
1567 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1568 return die_("setting APPLICATION data");
1569 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1570 return die_("copying object");
1571 if(!FLAC__metadata_iterator_set_block(iterator, app))
1572 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1574 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1575 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1576 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1577 return false;
1578 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1579 return false;
1581 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1582 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1583 return die_("copying object");
1584 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1585 return die_("setting APPLICATION data");
1586 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1587 return die_("copying object");
1588 if(!FLAC__metadata_iterator_set_block(iterator, app))
1589 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1591 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1592 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1593 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1594 return false;
1595 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1596 return false;
1598 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1599 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1600 return die_("creating PADDING block");
1601 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1602 return die_("copying object");
1603 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1604 return die_("setting APPLICATION data");
1605 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1606 return die_("copying object");
1607 padding->length = 0;
1608 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1609 return die_("internal error");
1610 if(!FLAC__metadata_iterator_set_block(iterator, app))
1611 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1613 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1614 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1615 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1616 return false;
1617 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1618 return false;
1620 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1621 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1622 return die_("copying object");
1623 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1624 return die_("setting APPLICATION data");
1625 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1626 return die_("copying object");
1627 our_metadata_.blocks[our_current_position+1]->length = 13;
1628 if(!FLAC__metadata_iterator_set_block(iterator, app))
1629 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1631 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1632 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1633 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1634 return false;
1635 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1636 return false;
1638 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1639 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1640 return die_("copying object");
1641 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1642 return die_("setting APPLICATION data");
1643 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1644 return die_("copying object");
1645 if(!FLAC__metadata_iterator_set_block(iterator, app))
1646 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1648 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1649 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1650 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1651 return false;
1652 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1653 return false;
1655 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1656 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1657 return die_("copying object");
1658 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1659 return die_("setting APPLICATION data");
1660 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1661 return die_("copying object");
1662 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1663 if(!FLAC__metadata_iterator_set_block(iterator, app))
1664 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1666 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1667 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1668 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1669 return false;
1670 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1671 return false;
1673 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1674 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1675 return die_("copying object");
1676 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1677 return die_("setting APPLICATION data");
1678 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1679 return die_("copying object");
1680 delete_from_our_metadata_(our_current_position+1);
1681 if(!FLAC__metadata_iterator_set_block(iterator, app))
1682 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1684 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1685 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1686 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1687 return false;
1688 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1689 return false;
1691 printf("SV[A]\tprev\n");
1692 if(!FLAC__metadata_iterator_prev(iterator))
1693 return die_("iterator ended early\n");
1694 our_current_position--;
1696 printf("S[V]A\tprev\n");
1697 if(!FLAC__metadata_iterator_prev(iterator))
1698 return die_("iterator ended early\n");
1699 our_current_position--;
1701 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1702 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1703 return die_("creating PADDING block");
1704 padding->length = 30;
1705 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1706 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1707 else
1708 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1710 printf("[S]VP\tnext\n");
1711 if(!FLAC__metadata_iterator_next(iterator))
1712 return die_("iterator ended early\n");
1713 our_current_position++;
1715 printf("S[V]A\tinsert PADDING after\n");
1716 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1717 return die_("copying metadata");
1718 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1719 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1721 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1722 return false;
1724 printf("SV[P]A\tinsert PADDING before\n");
1725 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1726 return die_("creating PADDING block");
1727 padding->length = 17;
1728 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1729 return die_("copying metadata");
1730 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1731 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1733 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1734 return false;
1736 printf("SV[P]PA\tinsert PADDING before\n");
1737 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1738 return die_("creating PADDING block");
1739 padding->length = 0;
1740 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1741 return die_("copying metadata");
1742 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1743 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1745 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1746 return false;
1748 printf("SV[P]PPA\tnext\n");
1749 if(!FLAC__metadata_iterator_next(iterator))
1750 return die_("iterator ended early\n");
1751 our_current_position++;
1753 printf("SVP[P]PA\tnext\n");
1754 if(!FLAC__metadata_iterator_next(iterator))
1755 return die_("iterator ended early\n");
1756 our_current_position++;
1758 printf("SVPP[P]A\tnext\n");
1759 if(!FLAC__metadata_iterator_next(iterator))
1760 return die_("iterator ended early\n");
1761 our_current_position++;
1763 printf("SVPPP[A]\tinsert PADDING after\n");
1764 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1765 return die_("creating PADDING block");
1766 padding->length = 57;
1767 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1768 return die_("copying metadata");
1769 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1770 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1772 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1773 return false;
1775 printf("SVPPPA[P]\tinsert PADDING before\n");
1776 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1777 return die_("creating PADDING block");
1778 padding->length = 99;
1779 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1780 return die_("copying metadata");
1781 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1782 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1784 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1785 return false;
1787 printf("delete iterator\n");
1788 FLAC__metadata_iterator_delete(iterator);
1789 our_current_position = 0;
1791 printf("SVPPPAPP\tmerge padding\n");
1792 FLAC__metadata_chain_merge_padding(chain);
1793 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1794 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1795 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1796 delete_from_our_metadata_(7);
1797 delete_from_our_metadata_(4);
1798 delete_from_our_metadata_(3);
1800 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1801 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1802 if(!compare_chain_(chain, 0, 0))
1803 return false;
1804 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1805 return false;
1807 printf("SVPAP\tsort padding\n");
1808 FLAC__metadata_chain_sort_padding(chain);
1809 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1810 delete_from_our_metadata_(2);
1812 if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1813 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1814 if(!compare_chain_(chain, 0, 0))
1815 return false;
1816 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1817 return false;
1819 printf("create iterator\n");
1820 if(0 == (iterator = FLAC__metadata_iterator_new()))
1821 return die_("allocating memory for iterator");
1823 our_current_position = 0;
1825 FLAC__metadata_iterator_init(iterator, chain);
1827 printf("[S]VAP\tnext\n");
1828 if(!FLAC__metadata_iterator_next(iterator))
1829 return die_("iterator ended early\n");
1830 our_current_position++;
1832 printf("S[V]AP\tnext\n");
1833 if(!FLAC__metadata_iterator_next(iterator))
1834 return die_("iterator ended early\n");
1835 our_current_position++;
1837 printf("SV[A]P\tdelete middle block, replace with padding\n");
1838 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1839 return die_("creating PADDING block");
1840 padding->length = 71;
1841 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1842 return die_("copying object");
1843 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1844 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1846 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1847 return false;
1849 printf("S[V]PP\tnext\n");
1850 if(!FLAC__metadata_iterator_next(iterator))
1851 return die_("iterator ended early\n");
1852 our_current_position++;
1854 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1855 delete_from_our_metadata_(our_current_position--);
1856 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1857 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1859 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1860 return false;
1862 printf("S[V]P\tnext\n");
1863 if(!FLAC__metadata_iterator_next(iterator))
1864 return die_("iterator ended early\n");
1865 our_current_position++;
1867 printf("SV[P]\tdelete last block, replace with padding\n");
1868 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1869 return die_("creating PADDING block");
1870 padding->length = 219;
1871 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1872 return die_("copying object");
1873 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1874 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1876 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1877 return false;
1879 printf("S[V]P\tnext\n");
1880 if(!FLAC__metadata_iterator_next(iterator))
1881 return die_("iterator ended early\n");
1882 our_current_position++;
1884 printf("SV[P]\tdelete last block, don't replace with padding\n");
1885 delete_from_our_metadata_(our_current_position--);
1886 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1887 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1889 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1890 return false;
1892 printf("S[V]\tprev\n");
1893 if(!FLAC__metadata_iterator_prev(iterator))
1894 return die_("iterator ended early\n");
1895 our_current_position--;
1897 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1898 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1899 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1901 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1902 return false;
1904 printf("delete iterator\n");
1905 FLAC__metadata_iterator_delete(iterator);
1906 our_current_position = 0;
1908 printf("SV\tmerge padding\n");
1909 FLAC__metadata_chain_merge_padding(chain);
1911 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1912 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1913 if(!compare_chain_(chain, 0, 0))
1914 return false;
1915 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1916 return false;
1918 printf("SV\tsort padding\n");
1919 FLAC__metadata_chain_sort_padding(chain);
1921 if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1922 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1923 if(!compare_chain_(chain, 0, 0))
1924 return false;
1925 if(!test_file_(is_ogg, decoder_metadata_callback_compare_))
1926 return false;
1928 end:
1929 printf("delete chain\n");
1931 FLAC__metadata_chain_delete(chain);
1933 if(!remove_file_(flacfilename(is_ogg)))
1934 return false;
1936 return true;
1939 static FLAC__bool test_level_2_misc_(FLAC__bool is_ogg)
1941 FLAC__Metadata_Iterator *iterator;
1942 FLAC__Metadata_Chain *chain;
1943 FLAC__IOCallbacks callbacks;
1945 memset(&callbacks, 0, sizeof(callbacks));
1946 callbacks.read = (FLAC__IOCallback_Read)fread;
1947 #ifdef FLAC__VALGRIND_TESTING
1948 callbacks.write = chain_write_cb_;
1949 #else
1950 callbacks.write = (FLAC__IOCallback_Write)fwrite;
1951 #endif
1952 callbacks.seek = chain_seek_cb_;
1953 callbacks.tell = chain_tell_cb_;
1954 callbacks.eof = chain_eof_cb_;
1956 printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
1958 printf("generate file\n");
1960 if(!generate_file_(/*include_extras=*/false, is_ogg))
1961 return false;
1963 printf("create chain\n");
1965 if(0 == (chain = FLAC__metadata_chain_new()))
1966 return die_("allocating chain");
1968 printf("read chain (filename-based)\n");
1970 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1971 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1973 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
1975 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
1976 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1977 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1978 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1979 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1982 printf("read chain (filename-based)\n");
1984 if(!FLAC__metadata_chain_read(chain, flacfilename(is_ogg)))
1985 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1987 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
1989 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
1990 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
1991 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
1992 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
1993 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
1996 printf("read chain (callback-based)\n");
1998 FILE *file = flac_fopen(flacfilename(is_ogg), "rb");
1999 if(0 == file)
2000 return die_("opening file");
2001 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2002 fclose(file);
2003 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2005 fclose(file);
2008 printf("write chain with wrong method FLAC__metadata_chain_write()\n");
2010 if(FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
2011 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2012 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2013 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", FLAC__metadata_chain_status(chain));
2014 printf(" OK: FLAC__metadata_chain_write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2017 printf("read chain (callback-based)\n");
2019 FILE *file = flac_fopen(flacfilename(is_ogg), "rb");
2020 if(0 == file)
2021 return die_("opening file");
2022 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2023 fclose(file);
2024 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2026 fclose(file);
2029 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2031 if(!FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2032 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned false like it should\n");
2033 else
2034 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned true but shouldn't have");
2036 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks_and_tempfile()\n");
2038 if(FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain, /*use_padding=*/false, 0, callbacks, 0, callbacks))
2039 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2040 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2041 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2042 printf(" OK: FLAC__metadata_chain_write_with_callbacks_and_tempfile() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2045 printf("read chain (callback-based)\n");
2047 FILE *file = flac_fopen(flacfilename(is_ogg), "rb");
2048 if(0 == file)
2049 return die_("opening file");
2050 if(!FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks)) {
2051 fclose(file);
2052 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
2054 fclose(file);
2057 printf("create iterator\n");
2058 if(0 == (iterator = FLAC__metadata_iterator_new()))
2059 return die_("allocating memory for iterator");
2061 FLAC__metadata_iterator_init(iterator, chain);
2063 printf("[S]VP\tnext\n");
2064 if(!FLAC__metadata_iterator_next(iterator))
2065 return die_("iterator ended early\n");
2067 printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2068 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
2069 return die_c_("block delete failed\n", FLAC__metadata_chain_status(chain));
2071 printf("testing FLAC__metadata_chain_check_if_tempfile_needed()... ");
2073 if(FLAC__metadata_chain_check_if_tempfile_needed(chain, /*use_padding=*/false))
2074 printf("OK: FLAC__metadata_chain_check_if_tempfile_needed() returned true like it should\n");
2075 else
2076 return die_("FLAC__metadata_chain_check_if_tempfile_needed() returned false but shouldn't have");
2078 printf("write chain with wrong method FLAC__metadata_chain_write_with_callbacks()\n");
2080 if(FLAC__metadata_chain_write_with_callbacks(chain, /*use_padding=*/false, 0, callbacks))
2081 return die_c_("mismatched write should have failed", FLAC__metadata_chain_status(chain));
2082 if(FLAC__metadata_chain_status(chain) != FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2083 return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", FLAC__metadata_chain_status(chain));
2084 printf(" OK: FLAC__metadata_chain_write_with_callbacks() returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2087 printf("delete iterator\n");
2089 FLAC__metadata_iterator_delete(iterator);
2091 printf("delete chain\n");
2093 FLAC__metadata_chain_delete(chain);
2095 if(!remove_file_(flacfilename(is_ogg)))
2096 return false;
2098 return true;
2101 FLAC__bool test_metadata_file_manipulation(void)
2103 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
2105 our_metadata_.num_blocks = 0;
2107 if(!test_level_0_())
2108 return false;
2110 if(!test_level_1_())
2111 return false;
2113 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2114 return false;
2115 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2116 return false;
2117 if(!test_level_2_misc_(/*is_ogg=*/false))
2118 return false;
2120 if(FLAC_API_SUPPORTS_OGG_FLAC) {
2121 if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2122 return false;
2123 if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2124 return false;
2125 #if 0
2126 /* when ogg flac write is supported, will have to add this: */
2127 if(!test_level_2_misc_(/*is_ogg=*/true))
2128 return false;
2129 #endif
2132 return true;