1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include "file_utils.h"
20 #include "metadata_utils.h"
21 #include "FLAC/assert.h"
22 #include "FLAC/file_decoder.h"
23 #include "FLAC/metadata.h"
24 #include "share/grabbag.h"
26 #include <stdlib.h> /* for malloc() */
28 /******************************************************************************
29 The general strategy of these tests (for interface levels 1 and 2) is
30 to create a dummy FLAC file with a known set of initial metadata
31 blocks, then keep a mirror locally of what we expect the metadata to be
32 after each operation. Then testing becomes a simple matter of running
33 a FLAC__FileDecoder over the dummy file after each operation, comparing
34 the decoded metadata to what's in our local copy. If there are any
35 differences in the metadata, or the actual audio data is corrupted, we
36 will catch it while decoding.
37 ******************************************************************************/
40 FLAC__bool error_occurred;
41 } decoder_client_struct;
44 FLAC__StreamMetadata *blocks[64];
46 } our_metadata_struct;
48 static const char *flacfile_ = "metadata.flac";
50 /* our copy of the metadata in flacfile_ */
51 static our_metadata_struct our_metadata_;
53 /* the current block number that corresponds to the position of the iterator we are testing */
54 static unsigned mc_our_block_number_ = 0;
56 static FLAC__bool die_(const char *msg)
58 printf("ERROR: %s\n", msg);
62 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
64 printf("ERROR: %s\n", msg);
65 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
69 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
71 printf("ERROR: %s\n", msg);
72 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
76 static void *malloc_or_die_(size_t size)
78 void *x = malloc(size);
80 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
86 /* functions for working with our metadata copy */
88 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
91 FLAC__StreamMetadata *obj = block;
92 FLAC__ASSERT(position < our_metadata_.num_blocks);
94 if(0 == (obj = FLAC__metadata_object_clone(block)))
95 return die_("during FLAC__metadata_object_clone()");
97 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
98 our_metadata_.blocks[position] = obj;
100 /* set the is_last flags */
101 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
102 our_metadata_.blocks[i]->is_last = false;
103 our_metadata_.blocks[i]->is_last = true;
108 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
111 FLAC__StreamMetadata *obj = block;
113 if(0 == (obj = FLAC__metadata_object_clone(block)))
114 return die_("during FLAC__metadata_object_clone()");
116 if(position > our_metadata_.num_blocks) {
117 position = our_metadata_.num_blocks;
120 for(i = our_metadata_.num_blocks; i > position; i--)
121 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
123 our_metadata_.blocks[position] = obj;
124 our_metadata_.num_blocks++;
126 /* set the is_last flags */
127 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
128 our_metadata_.blocks[i]->is_last = false;
129 our_metadata_.blocks[i]->is_last = true;
134 static void delete_from_our_metadata_(unsigned position)
137 FLAC__ASSERT(position < our_metadata_.num_blocks);
138 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
139 for(i = position; i < our_metadata_.num_blocks - 1; i++)
140 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
141 our_metadata_.num_blocks--;
143 /* set the is_last flags */
144 if(our_metadata_.num_blocks > 0) {
145 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
146 our_metadata_.blocks[i]->is_last = false;
147 our_metadata_.blocks[i]->is_last = true;
151 /* function for comparing our metadata to a FLAC__Metadata_Chain */
153 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
156 FLAC__Metadata_Iterator *iterator;
157 FLAC__StreamMetadata *block;
158 FLAC__bool next_ok = true;
160 FLAC__ASSERT(0 != chain);
162 printf("\tcomparing chain... ");
165 if(0 == (iterator = FLAC__metadata_iterator_new()))
166 return die_("allocating memory for iterator");
168 FLAC__metadata_iterator_init(iterator, chain);
175 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
176 FLAC__metadata_iterator_delete(iterator);
177 return die_("getting block from iterator");
180 if(!compare_block_(our_metadata_.blocks[i], block)) {
181 FLAC__metadata_iterator_delete(iterator);
182 return die_("metadata block mismatch");
186 next_ok = FLAC__metadata_iterator_next(iterator);
187 } while(i < our_metadata_.num_blocks && next_ok);
189 FLAC__metadata_iterator_delete(iterator);
192 return die_("chain has more blocks than expected");
194 if(i < our_metadata_.num_blocks)
195 return die_("short block count in chain");
197 if(0 != current_block) {
198 printf("CURRENT_POSITION... ");
201 if(!compare_block_(our_metadata_.blocks[current_position], current_block))
202 return die_("metadata block mismatch");
210 /* decoder callbacks for checking the file */
212 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
214 (void)decoder, (void)buffer, (void)client_data;
217 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
218 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
220 printf("content... ");
224 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
227 /* this version pays no attention to the metadata */
228 static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
230 (void)decoder, (void)metadata, (void)client_data;
232 printf("%d... ", mc_our_block_number_);
235 mc_our_block_number_++;
238 /* this version is used when we want to compare to our metadata copy */
239 static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
241 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
245 /* don't bother checking if we've already hit an error */
246 if(dcd->error_occurred)
249 printf("%d... ", mc_our_block_number_);
252 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
253 (void)die_("got more metadata blocks than expected");
254 dcd->error_occurred = true;
257 if(!compare_block_(our_metadata_.blocks[mc_our_block_number_], metadata)) {
258 (void)die_("metadata block mismatch");
259 dcd->error_occurred = true;
262 mc_our_block_number_++;
265 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
267 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
270 dcd->error_occurred = true;
271 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
274 static FLAC__bool generate_file_()
276 FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
277 FLAC__StreamMetadata *metadata[1];
279 printf("generating FLAC file for test\n");
281 while(our_metadata_.num_blocks > 0)
282 delete_from_our_metadata_(0);
284 streaminfo.is_last = false;
285 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
286 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
287 streaminfo.data.stream_info.min_blocksize = 576;
288 streaminfo.data.stream_info.max_blocksize = 576;
289 streaminfo.data.stream_info.min_framesize = 0;
290 streaminfo.data.stream_info.max_framesize = 0;
291 streaminfo.data.stream_info.sample_rate = 44100;
292 streaminfo.data.stream_info.channels = 1;
293 streaminfo.data.stream_info.bits_per_sample = 8;
294 streaminfo.data.stream_info.total_samples = 0;
295 memset(streaminfo.data.stream_info.md5sum, 0, 16);
298 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
299 vorbiscomment.is_last = false;
300 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
301 vorbiscomment.length = (4 + vendor_string_length) + 4;
302 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
303 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length);
304 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length);
305 vorbiscomment.data.vorbis_comment.num_comments = 0;
306 vorbiscomment.data.vorbis_comment.comments = 0;
309 padding.is_last = true;
310 padding.type = FLAC__METADATA_TYPE_PADDING;
311 padding.length = 1234;
313 metadata[0] = &padding;
316 !insert_to_our_metadata_(&streaminfo, 0, /*copy=*/true) ||
317 !insert_to_our_metadata_(&vorbiscomment, 1, /*copy=*/true) ||
318 !insert_to_our_metadata_(&padding, 2, /*copy=*/true)
320 return die_("priming our metadata");
322 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
323 return die_("creating the encoded file");
325 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
330 static FLAC__bool test_file_(const char *filename, void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data))
332 FLAC__FileDecoder *decoder;
333 decoder_client_struct decoder_client_data;
335 FLAC__ASSERT(0 != filename);
336 FLAC__ASSERT(0 != metadata_callback);
338 mc_our_block_number_ = 0;
339 decoder_client_data.error_occurred = false;
341 printf("\ttesting '%s'... ", filename);
344 if(0 == (decoder = FLAC__file_decoder_new()))
345 return die_("couldn't allocate decoder instance");
347 FLAC__file_decoder_set_md5_checking(decoder, true);
348 FLAC__file_decoder_set_filename(decoder, filename);
349 FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
350 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
351 FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
352 FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
353 FLAC__file_decoder_set_metadata_respond_all(decoder);
354 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
355 FLAC__file_decoder_finish(decoder);
356 FLAC__file_decoder_delete(decoder);
357 return die_("initializing decoder\n");
359 if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
360 FLAC__file_decoder_finish(decoder);
361 FLAC__file_decoder_delete(decoder);
362 return die_("decoding file\n");
365 FLAC__file_decoder_finish(decoder);
366 FLAC__file_decoder_delete(decoder);
368 if(decoder_client_data.error_occurred)
371 if(mc_our_block_number_ != our_metadata_.num_blocks)
372 return die_("short metadata block count");
378 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
380 if(!grabbag__file_change_stats(filename, read_only))
381 return die_("during grabbag__file_change_stats()");
386 static FLAC__bool remove_file_(const char *filename)
388 while(our_metadata_.num_blocks > 0)
389 delete_from_our_metadata_(0);
391 if(!grabbag__file_remove_file(filename))
392 return die_("removing file");
397 static FLAC__bool test_level_0_()
399 FLAC__StreamMetadata streaminfo;
401 printf("\n\n++++++ testing level 0 interface\n");
403 if(!generate_file_())
406 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
409 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
410 return die_("during FLAC__metadata_get_streaminfo()");
412 /* check to see if some basic data matches (c.f. generate_file_()) */
413 if(streaminfo.data.stream_info.channels != 1)
414 return die_("mismatch in streaminfo.data.stream_info.channels");
415 if(streaminfo.data.stream_info.bits_per_sample != 8)
416 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
417 if(streaminfo.data.stream_info.sample_rate != 44100)
418 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
419 if(streaminfo.data.stream_info.min_blocksize != 576)
420 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
421 if(streaminfo.data.stream_info.max_blocksize != 576)
422 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
424 if(!remove_file_(flacfile_))
430 static FLAC__bool test_level_1_()
432 FLAC__Metadata_SimpleIterator *iterator;
433 FLAC__StreamMetadata *block, *app, *padding;
434 FLAC__byte data[1000];
435 unsigned our_current_position = 0;
437 printf("\n\n++++++ testing level 1 interface\n");
439 /************************************************************/
441 printf("simple iterator on read-only file\n");
443 if(!generate_file_())
446 if(!change_stats_(flacfile_, /*read_only=*/true))
449 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
452 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
453 return die_("FLAC__metadata_simple_iterator_new()");
455 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
456 return die_("FLAC__metadata_simple_iterator_init() returned false");
458 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
459 if(FLAC__metadata_simple_iterator_is_writable(iterator))
460 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
462 printf("iterate forwards\n");
464 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
465 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
466 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
467 return die_("getting block 0");
468 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
469 return die_("expected STREAMINFO type");
471 return die_("expected is_last to be false");
472 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
473 return die_("bad STREAMINFO length");
474 /* check to see if some basic data matches (c.f. generate_file_()) */
475 if(block->data.stream_info.channels != 1)
476 return die_("mismatch in channels");
477 if(block->data.stream_info.bits_per_sample != 8)
478 return die_("mismatch in bits_per_sample");
479 if(block->data.stream_info.sample_rate != 44100)
480 return die_("mismatch in sample_rate");
481 if(block->data.stream_info.min_blocksize != 576)
482 return die_("mismatch in min_blocksize");
483 if(block->data.stream_info.max_blocksize != 576)
484 return die_("mismatch in max_blocksize");
485 FLAC__metadata_object_delete(block);
487 if(!FLAC__metadata_simple_iterator_next(iterator))
488 return die_("forward iterator ended early");
489 our_current_position++;
491 if(!FLAC__metadata_simple_iterator_next(iterator))
492 return die_("forward iterator ended early");
493 our_current_position++;
495 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
496 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
497 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
498 return die_("getting block 2");
499 if(block->type != FLAC__METADATA_TYPE_PADDING)
500 return die_("expected PADDING type");
502 return die_("expected is_last to be true");
503 /* check to see if some basic data matches (c.f. generate_file_()) */
504 if(block->length != 1234)
505 return die_("bad PADDING length");
506 FLAC__metadata_object_delete(block);
508 if(FLAC__metadata_simple_iterator_next(iterator))
509 return die_("forward iterator returned true but should have returned false");
511 printf("iterate backwards\n");
512 if(!FLAC__metadata_simple_iterator_prev(iterator))
513 return die_("reverse iterator ended early");
514 if(!FLAC__metadata_simple_iterator_prev(iterator))
515 return die_("reverse iterator ended early");
516 if(FLAC__metadata_simple_iterator_prev(iterator))
517 return die_("reverse iterator returned true but should have returned false");
519 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
521 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
522 printf("PASSED. FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
524 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
526 FLAC__metadata_simple_iterator_delete(iterator);
528 /************************************************************/
530 printf("simple iterator on writable file\n");
532 if(!change_stats_(flacfile_, /*read-only=*/false))
535 printf("creating APPLICATION block\n");
537 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
538 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
539 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
541 printf("creating PADDING block\n");
543 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
544 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
545 padding->length = 20;
547 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
548 return die_("FLAC__metadata_simple_iterator_new()");
550 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
551 return die_("FLAC__metadata_simple_iterator_init() returned false");
552 our_current_position = 0;
554 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
556 printf("[S]VP\ttry to write over STREAMINFO block...\n");
557 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
558 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
560 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
562 printf("[S]VP\tnext\n");
563 if(!FLAC__metadata_simple_iterator_next(iterator))
564 return die_("iterator ended early\n");
565 our_current_position++;
567 printf("S[V]P\tnext\n");
568 if(!FLAC__metadata_simple_iterator_next(iterator))
569 return die_("iterator ended early\n");
570 our_current_position++;
572 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
573 padding->length = 25;
574 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
575 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
576 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
579 printf("SVP[P]\tprev\n");
580 if(!FLAC__metadata_simple_iterator_prev(iterator))
581 return die_("iterator ended early\n");
582 our_current_position--;
584 printf("SV[P]P\tprev\n");
585 if(!FLAC__metadata_simple_iterator_prev(iterator))
586 return die_("iterator ended early\n");
587 our_current_position--;
589 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
590 padding->length = 30;
591 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
592 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
593 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
596 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
599 printf("SV[P]PP\tprev\n");
600 if(!FLAC__metadata_simple_iterator_prev(iterator))
601 return die_("iterator ended early\n");
602 our_current_position--;
604 printf("S[V]PPP\tprev\n");
605 if(!FLAC__metadata_simple_iterator_prev(iterator))
606 return die_("iterator ended early\n");
607 our_current_position--;
609 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
610 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
611 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
613 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
616 printf("[S]VPPP\tnext\n");
617 if(!FLAC__metadata_simple_iterator_next(iterator))
618 return die_("iterator ended early\n");
619 our_current_position++;
621 printf("S[V]PPP\tnext\n");
622 if(!FLAC__metadata_simple_iterator_next(iterator))
623 return die_("iterator ended early\n");
624 our_current_position++;
626 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
627 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
628 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
629 our_current_position--;
631 printf("S[V]PPP\tnext\n");
632 if(!FLAC__metadata_simple_iterator_next(iterator))
633 return die_("iterator ended early\n");
634 our_current_position++;
636 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
637 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
638 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
639 delete_from_our_metadata_(our_current_position--);
641 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
644 printf("S[V]PP\tnext\n");
645 if(!FLAC__metadata_simple_iterator_next(iterator))
646 return die_("iterator ended early\n");
647 our_current_position++;
649 printf("SV[P]P\tnext\n");
650 if(!FLAC__metadata_simple_iterator_next(iterator))
651 return die_("iterator ended early\n");
652 our_current_position++;
654 printf("SVP[P]\tdelete (last block), replace with padding\n");
655 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
656 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
657 our_current_position--;
659 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
662 printf("SV[P]P\tnext\n");
663 if(!FLAC__metadata_simple_iterator_next(iterator))
664 return die_("iterator ended early\n");
665 our_current_position++;
667 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
668 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
669 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
670 delete_from_our_metadata_(our_current_position--);
672 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
675 printf("SV[P]\tprev\n");
676 if(!FLAC__metadata_simple_iterator_prev(iterator))
677 return die_("iterator ended early\n");
678 our_current_position--;
680 printf("S[V]P\tprev\n");
681 if(!FLAC__metadata_simple_iterator_prev(iterator))
682 return die_("iterator ended early\n");
683 our_current_position--;
685 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
686 FLAC__ASSERT(our_current_position == 0);
687 block = FLAC__metadata_simple_iterator_get_block(iterator);
688 block->data.stream_info.sample_rate = 32000;
689 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
690 return die_("copying object");
691 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
692 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
693 FLAC__metadata_object_delete(block);
695 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
698 printf("[S]VP\tnext\n");
699 if(!FLAC__metadata_simple_iterator_next(iterator))
700 return die_("iterator ended early\n");
701 our_current_position++;
703 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
704 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
705 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
706 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
707 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
709 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
711 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
714 printf("SV[A]P\tnext\n");
715 if(!FLAC__metadata_simple_iterator_next(iterator))
716 return die_("iterator ended early\n");
717 our_current_position++;
719 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
720 app->data.application.id[0] = 'f'; /* twiddle the id */
721 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
722 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
723 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
725 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
727 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
730 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
731 app->data.application.id[0] = 'g'; /* twiddle the id */
732 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
733 return die_("setting APPLICATION data");
734 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
735 return die_("copying object");
736 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
737 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
739 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
742 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
743 app->data.application.id[0] = 'h'; /* twiddle the id */
744 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
745 return die_("setting APPLICATION data");
746 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
747 return die_("copying object");
748 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
749 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
751 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
754 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
755 app->data.application.id[0] = 'i'; /* twiddle the id */
756 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
757 return die_("setting APPLICATION data");
758 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
759 return die_("copying object");
760 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
761 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
762 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
764 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
767 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
768 app->data.application.id[0] = 'j'; /* twiddle the id */
769 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
770 return die_("setting APPLICATION data");
771 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
772 return die_("copying object");
773 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
774 return die_("copying object");
775 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
776 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
777 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
779 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
782 printf("SVA[A]PP\tnext\n");
783 if(!FLAC__metadata_simple_iterator_next(iterator))
784 return die_("iterator ended early\n");
785 our_current_position++;
787 printf("SVAA[P]P\tnext\n");
788 if(!FLAC__metadata_simple_iterator_next(iterator))
789 return die_("iterator ended early\n");
790 our_current_position++;
792 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
794 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
795 return die_("copying object");
796 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
797 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
799 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
802 printf("SVAAP[P]\tset APPLICATION (grow)\n");
803 app->data.application.id[0] = 'k'; /* twiddle the id */
804 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
805 return die_("copying object");
806 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
807 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
809 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
812 printf("SVAAP[A]\tset PADDING (equal)\n");
813 padding->length = 27;
814 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
815 return die_("copying object");
816 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
817 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
819 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
822 printf("SVAAP[P]\tprev\n");
823 if(!FLAC__metadata_simple_iterator_prev(iterator))
824 return die_("iterator ended early\n");
825 our_current_position--;
827 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
828 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
829 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
830 delete_from_our_metadata_(our_current_position--);
832 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
835 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
836 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
837 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
838 delete_from_our_metadata_(our_current_position--);
840 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
843 printf("SV[A]P\tnext\n");
844 if(!FLAC__metadata_simple_iterator_next(iterator))
845 return die_("iterator ended early\n");
846 our_current_position++;
848 printf("SVA[P]\tinsert PADDING after\n");
850 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
851 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
852 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
855 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
858 printf("SVAP[P]\tprev\n");
859 if(!FLAC__metadata_simple_iterator_prev(iterator))
860 return die_("iterator ended early\n");
861 our_current_position--;
863 printf("SVA[P]P\tprev\n");
864 if(!FLAC__metadata_simple_iterator_prev(iterator))
865 return die_("iterator ended early\n");
866 our_current_position--;
868 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
869 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
870 return die_("setting APPLICATION data");
871 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
872 return die_("copying object");
873 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
874 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
876 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
879 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
880 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
881 return die_("setting APPLICATION data");
882 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
883 return die_("copying object");
884 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
885 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
887 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
890 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
891 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
892 return die_("setting APPLICATION data");
893 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
894 return die_("copying object");
895 our_metadata_.blocks[our_current_position+1]->length = 0;
896 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
897 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
899 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
902 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
903 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
904 return die_("setting APPLICATION data");
905 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
906 return die_("copying object");
907 delete_from_our_metadata_(our_current_position+1);
908 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
909 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
911 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
914 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
915 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
916 return die_("setting APPLICATION data");
917 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
918 return die_("copying object");
919 delete_from_our_metadata_(our_current_position+1);
920 our_metadata_.blocks[our_current_position]->is_last = true;
921 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
922 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
924 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
927 printf("SV[A]\tset PADDING (equal size)\n");
928 padding->length = app->length;
929 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
930 return die_("copying object");
931 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
932 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
934 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
937 printf("SV[P]\tinsert PADDING after\n");
938 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
939 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
940 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
943 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
946 printf("SVP[P]\tinsert PADDING after\n");
948 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
949 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
950 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
953 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
956 printf("SVPP[P]\tprev\n");
957 if(!FLAC__metadata_simple_iterator_prev(iterator))
958 return die_("iterator ended early\n");
959 our_current_position--;
961 printf("SVP[P]P\tprev\n");
962 if(!FLAC__metadata_simple_iterator_prev(iterator))
963 return die_("iterator ended early\n");
964 our_current_position--;
966 printf("SV[P]PP\tprev\n");
967 if(!FLAC__metadata_simple_iterator_prev(iterator))
968 return die_("iterator ended early\n");
969 our_current_position--;
971 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
972 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
973 return die_("setting APPLICATION data");
974 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
975 return die_("copying object");
976 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
977 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
979 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
982 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
983 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
984 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
985 delete_from_our_metadata_(our_current_position--);
987 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
990 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
991 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
992 return die_("setting APPLICATION data");
993 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
994 return die_("copying object");
995 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
996 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
998 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1001 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1002 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1003 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1004 delete_from_our_metadata_(our_current_position--);
1006 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1009 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1010 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1011 return die_("setting APPLICATION data");
1012 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1013 return die_("copying object");
1014 delete_from_our_metadata_(our_current_position+1);
1015 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1016 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1018 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1021 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1022 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1023 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1024 delete_from_our_metadata_(our_current_position--);
1026 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1029 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1030 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1031 return die_("setting APPLICATION data");
1032 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1033 return die_("copying object");
1034 our_metadata_.blocks[our_current_position+1]->length = 0;
1035 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1036 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1038 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1041 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1042 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1043 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1044 delete_from_our_metadata_(our_current_position--);
1046 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1049 printf("S[V]PP\tnext\n");
1050 if(!FLAC__metadata_simple_iterator_next(iterator))
1051 return die_("iterator ended early\n");
1052 our_current_position++;
1054 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1055 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1056 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1057 delete_from_our_metadata_(our_current_position--);
1059 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1062 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1063 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1064 return die_("setting APPLICATION data");
1065 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1066 return die_("copying object");
1067 delete_from_our_metadata_(our_current_position+1);
1068 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1069 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1071 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1074 printf("delete simple iterator\n");
1076 FLAC__metadata_simple_iterator_delete(iterator);
1078 FLAC__metadata_object_delete(app);
1079 FLAC__metadata_object_delete(padding);
1081 if(!remove_file_(flacfile_))
1087 static FLAC__bool test_level_2_()
1089 FLAC__Metadata_Iterator *iterator;
1090 FLAC__Metadata_Chain *chain;
1091 FLAC__StreamMetadata *block, *app, *padding;
1092 FLAC__byte data[2000];
1093 unsigned our_current_position;
1095 printf("\n\n++++++ testing level 2 interface\n");
1097 printf("generate read-only file\n");
1099 if(!generate_file_())
1102 if(!change_stats_(flacfile_, /*read_only=*/true))
1105 printf("create chain\n");
1107 if(0 == (chain = FLAC__metadata_chain_new()))
1108 return die_("allocating chain");
1110 printf("read chain\n");
1112 if(!FLAC__metadata_chain_read(chain, flacfile_))
1113 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1115 printf("[S]VP\ttest initial metadata\n");
1117 if(!compare_chain_(chain, 0, 0))
1119 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1122 printf("switch file to read-write\n");
1124 if(!change_stats_(flacfile_, /*read-only=*/false))
1127 printf("create iterator\n");
1128 if(0 == (iterator = FLAC__metadata_iterator_new()))
1129 return die_("allocating memory for iterator");
1131 our_current_position = 0;
1133 FLAC__metadata_iterator_init(iterator, chain);
1135 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1136 return die_("getting block from iterator");
1138 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1140 printf("[S]VP\tmodify STREAMINFO, write\n");
1142 block->data.stream_info.sample_rate = 32000;
1143 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1144 return die_("copying object");
1146 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/true))
1147 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1148 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1150 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1153 printf("[S]VP\tnext\n");
1154 if(!FLAC__metadata_iterator_next(iterator))
1155 return die_("iterator ended early\n");
1156 our_current_position++;
1158 printf("S[V]P\tnext\n");
1159 if(!FLAC__metadata_iterator_next(iterator))
1160 return die_("iterator ended early\n");
1161 our_current_position++;
1163 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1164 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1165 return die_("getting block from iterator");
1166 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1167 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1168 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1169 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1170 return die_("setting APPLICATION data");
1171 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1172 return die_("copying object");
1173 if(!FLAC__metadata_iterator_set_block(iterator, app))
1174 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1176 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1177 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1178 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1180 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1183 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1184 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1185 return die_("copying object");
1186 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1187 return die_("setting APPLICATION data");
1188 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1189 return die_("copying object");
1190 if(!FLAC__metadata_iterator_set_block(iterator, app))
1191 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1193 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1194 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1195 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1197 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1200 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1201 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1202 return die_("copying object");
1203 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1204 return die_("setting APPLICATION data");
1205 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1206 return die_("copying object");
1207 if(!FLAC__metadata_iterator_set_block(iterator, app))
1208 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1210 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1211 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1212 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1214 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1217 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1218 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1219 return die_("copying object");
1220 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1221 return die_("setting APPLICATION data");
1222 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1223 return die_("copying object");
1224 if(!FLAC__metadata_iterator_set_block(iterator, app))
1225 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1227 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1228 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1229 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1231 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1234 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1235 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1236 return die_("copying object");
1237 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1238 return die_("setting APPLICATION data");
1239 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1240 return die_("copying object");
1241 if(!FLAC__metadata_iterator_set_block(iterator, app))
1242 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1244 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1245 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1246 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1248 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1251 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1252 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1253 return die_("creating PADDING block");
1254 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1255 return die_("copying object");
1256 if(!FLAC__metadata_object_application_set_data(app, data, 29, 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 padding->length = 0;
1261 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1262 return die_("internal error");
1263 if(!FLAC__metadata_iterator_set_block(iterator, app))
1264 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1266 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1267 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1268 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1270 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1273 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1274 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1275 return die_("copying object");
1276 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1277 return die_("setting APPLICATION data");
1278 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1279 return die_("copying object");
1280 our_metadata_.blocks[our_current_position+1]->length = 13;
1281 if(!FLAC__metadata_iterator_set_block(iterator, app))
1282 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1284 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1285 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1286 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1288 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1291 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1292 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1293 return die_("copying object");
1294 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1295 return die_("setting APPLICATION data");
1296 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1297 return die_("copying object");
1298 if(!FLAC__metadata_iterator_set_block(iterator, app))
1299 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1301 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1302 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1303 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1305 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1308 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1309 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1310 return die_("copying object");
1311 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1312 return die_("setting APPLICATION data");
1313 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1314 return die_("copying object");
1315 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1316 if(!FLAC__metadata_iterator_set_block(iterator, app))
1317 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1319 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1320 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1321 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1323 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1326 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1327 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1328 return die_("copying object");
1329 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1330 return die_("setting APPLICATION data");
1331 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1332 return die_("copying object");
1333 delete_from_our_metadata_(our_current_position+1);
1334 if(!FLAC__metadata_iterator_set_block(iterator, app))
1335 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1337 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1338 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1339 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1341 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1344 printf("SV[A]\tprev\n");
1345 if(!FLAC__metadata_iterator_prev(iterator))
1346 return die_("iterator ended early\n");
1347 our_current_position--;
1349 printf("S[V]A\tprev\n");
1350 if(!FLAC__metadata_iterator_prev(iterator))
1351 return die_("iterator ended early\n");
1352 our_current_position--;
1354 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1355 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1356 return die_("creating PADDING block");
1357 padding->length = 30;
1358 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1359 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1361 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1363 printf("[S]VP\tnext\n");
1364 if(!FLAC__metadata_iterator_next(iterator))
1365 return die_("iterator ended early\n");
1366 our_current_position++;
1368 printf("S[V]A\tinsert PADDING after\n");
1369 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1370 return die_("copying metadata");
1371 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1372 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1374 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1377 printf("SV[P]A\tinsert PADDING before\n");
1378 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1379 return die_("creating PADDING block");
1380 padding->length = 17;
1381 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1382 return die_("copying metadata");
1383 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1384 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1386 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1389 printf("SV[P]PA\tinsert PADDING before\n");
1390 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1391 return die_("creating PADDING block");
1392 padding->length = 0;
1393 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1394 return die_("copying metadata");
1395 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1396 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1398 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1401 printf("SV[P]PPA\tnext\n");
1402 if(!FLAC__metadata_iterator_next(iterator))
1403 return die_("iterator ended early\n");
1404 our_current_position++;
1406 printf("SVP[P]PA\tnext\n");
1407 if(!FLAC__metadata_iterator_next(iterator))
1408 return die_("iterator ended early\n");
1409 our_current_position++;
1411 printf("SVPP[P]A\tnext\n");
1412 if(!FLAC__metadata_iterator_next(iterator))
1413 return die_("iterator ended early\n");
1414 our_current_position++;
1416 printf("SVPPP[A]\tinsert PADDING after\n");
1417 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1418 return die_("creating PADDING block");
1419 padding->length = 57;
1420 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1421 return die_("copying metadata");
1422 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1423 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1425 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1428 printf("SVPPPA[P]\tinsert PADDING before\n");
1429 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1430 return die_("creating PADDING block");
1431 padding->length = 99;
1432 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1433 return die_("copying metadata");
1434 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1435 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1437 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1440 printf("delete iterator\n");
1441 FLAC__metadata_iterator_delete(iterator);
1442 our_current_position = 0;
1444 printf("SVPPPAPP\tmerge padding\n");
1445 FLAC__metadata_chain_merge_padding(chain);
1446 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1447 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1448 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1449 delete_from_our_metadata_(7);
1450 delete_from_our_metadata_(4);
1451 delete_from_our_metadata_(3);
1453 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1454 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1455 if(!compare_chain_(chain, 0, 0))
1457 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1460 printf("SVPAP\tsort padding\n");
1461 FLAC__metadata_chain_sort_padding(chain);
1462 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1463 delete_from_our_metadata_(2);
1465 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1466 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1467 if(!compare_chain_(chain, 0, 0))
1469 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
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 printf("[S]VAP\tnext\n");
1481 if(!FLAC__metadata_iterator_next(iterator))
1482 return die_("iterator ended early\n");
1483 our_current_position++;
1485 printf("S[V]AP\tnext\n");
1486 if(!FLAC__metadata_iterator_next(iterator))
1487 return die_("iterator ended early\n");
1488 our_current_position++;
1490 printf("SV[A]P\tdelete middle block, replace with padding\n");
1491 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1492 return die_("creating PADDING block");
1493 padding->length = 71;
1494 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1495 return die_("copying object");
1496 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1497 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1499 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1502 printf("S[V]PP\tnext\n");
1503 if(!FLAC__metadata_iterator_next(iterator))
1504 return die_("iterator ended early\n");
1505 our_current_position++;
1507 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1508 delete_from_our_metadata_(our_current_position--);
1509 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1510 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1512 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1515 printf("S[V]P\tnext\n");
1516 if(!FLAC__metadata_iterator_next(iterator))
1517 return die_("iterator ended early\n");
1518 our_current_position++;
1520 printf("SV[P]\tdelete last block, replace with padding\n");
1521 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1522 return die_("creating PADDING block");
1523 padding->length = 219;
1524 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1525 return die_("copying object");
1526 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1527 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1529 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1532 printf("S[V]P\tnext\n");
1533 if(!FLAC__metadata_iterator_next(iterator))
1534 return die_("iterator ended early\n");
1535 our_current_position++;
1537 printf("SV[P]\tdelete last block, don't replace with padding\n");
1538 delete_from_our_metadata_(our_current_position--);
1539 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1540 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1542 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1545 printf("S[V]\tprev\n");
1546 if(!FLAC__metadata_iterator_prev(iterator))
1547 return die_("iterator ended early\n");
1548 our_current_position--;
1550 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1551 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1552 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1554 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1557 printf("delete iterator\n");
1558 FLAC__metadata_iterator_delete(iterator);
1559 our_current_position = 0;
1561 printf("SV\tmerge padding\n");
1562 FLAC__metadata_chain_merge_padding(chain);
1564 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1565 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1566 if(!compare_chain_(chain, 0, 0))
1568 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1571 printf("SV\tsort padding\n");
1572 FLAC__metadata_chain_sort_padding(chain);
1574 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1575 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1576 if(!compare_chain_(chain, 0, 0))
1578 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1581 printf("delete chain\n");
1583 FLAC__metadata_chain_delete(chain);
1585 if(!remove_file_(flacfile_))
1591 FLAC__bool test_metadata_file_manipulation()
1593 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1595 our_metadata_.num_blocks = 0;
1597 if(!test_level_0_())
1600 if(!test_level_1_())
1603 if(!test_level_2_())