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"
25 #include <stdlib.h> /* for malloc() */
27 /******************************************************************************
28 The general strategy of these tests (for interface levels 1 and 2) is
29 to create a dummy FLAC file with a known set of initial metadata
30 blocks, then keep a mirror locally of what we expect the metadata to be
31 after each operation. Then testing becomes a simple matter of running
32 a FLAC__FileDecoder over the dummy file after each operation, comparing
33 the decoded metadata to what's in our local copy. If there are any
34 differences in the metadata, or the actual audio data is corrupted, we
35 will catch it while decoding.
36 ******************************************************************************/
39 FLAC__bool error_occurred;
40 } decoder_client_struct;
43 FLAC__StreamMetadata *blocks[64];
45 } our_metadata_struct;
47 static const char *flacfile_ = "metadata.flac";
49 /* our copy of the metadata in flacfile_ */
50 static our_metadata_struct our_metadata_;
52 /* the current block number that corresponds to the position of the iterator we are testing */
53 static unsigned mc_our_block_number_ = 0;
55 static FLAC__bool die_(const char *msg)
57 printf("ERROR: %s\n", msg);
61 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
63 printf("ERROR: %s\n", msg);
64 printf(" status=%s\n", FLAC__Metadata_ChainStatusString[status]);
68 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
70 printf("ERROR: %s\n", msg);
71 printf(" status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
75 static void *malloc_or_die_(size_t size)
77 void *x = malloc(size);
79 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
85 /* functions for working with our metadata copy */
87 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
90 FLAC__StreamMetadata *obj = block;
91 FLAC__ASSERT(position < our_metadata_.num_blocks);
93 if(0 == (obj = FLAC__metadata_object_clone(block)))
94 return die_("during FLAC__metadata_object_clone()");
96 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
97 our_metadata_.blocks[position] = obj;
99 /* set the is_last flags */
100 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
101 our_metadata_.blocks[i]->is_last = false;
102 our_metadata_.blocks[i]->is_last = true;
107 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
110 FLAC__StreamMetadata *obj = block;
112 if(0 == (obj = FLAC__metadata_object_clone(block)))
113 return die_("during FLAC__metadata_object_clone()");
115 if(position > our_metadata_.num_blocks) {
116 position = our_metadata_.num_blocks;
119 for(i = our_metadata_.num_blocks; i > position; i--)
120 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
122 our_metadata_.blocks[position] = obj;
123 our_metadata_.num_blocks++;
125 /* set the is_last flags */
126 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
127 our_metadata_.blocks[i]->is_last = false;
128 our_metadata_.blocks[i]->is_last = true;
133 static void delete_from_our_metadata_(unsigned position)
136 FLAC__ASSERT(position < our_metadata_.num_blocks);
137 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
138 for(i = position; i < our_metadata_.num_blocks - 1; i++)
139 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
140 our_metadata_.num_blocks--;
142 /* set the is_last flags */
143 if(our_metadata_.num_blocks > 0) {
144 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
145 our_metadata_.blocks[i]->is_last = false;
146 our_metadata_.blocks[i]->is_last = true;
150 /* function for comparing our metadata to a FLAC__Metadata_Chain */
152 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
155 FLAC__Metadata_Iterator *iterator;
156 FLAC__StreamMetadata *block;
157 FLAC__bool next_ok = true;
159 FLAC__ASSERT(0 != chain);
161 printf("\tcomparing chain... ");
164 if(0 == (iterator = FLAC__metadata_iterator_new()))
165 return die_("allocating memory for iterator");
167 FLAC__metadata_iterator_init(iterator, chain);
174 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
175 FLAC__metadata_iterator_delete(iterator);
176 return die_("getting block from iterator");
179 if(!compare_block_(our_metadata_.blocks[i], block)) {
180 FLAC__metadata_iterator_delete(iterator);
181 return die_("metadata block mismatch");
185 next_ok = FLAC__metadata_iterator_next(iterator);
186 } while(i < our_metadata_.num_blocks && next_ok);
188 FLAC__metadata_iterator_delete(iterator);
191 return die_("chain has more blocks than expected");
193 if(i < our_metadata_.num_blocks)
194 return die_("short block count in chain");
196 if(0 != current_block) {
197 printf("CURRENT_POSITION... ");
200 if(!compare_block_(our_metadata_.blocks[current_position], current_block))
201 return die_("metadata block mismatch");
209 /* decoder callbacks for checking the file */
211 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
213 (void)decoder, (void)buffer, (void)client_data;
216 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
217 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
219 printf("content... ");
223 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
226 /* this version pays no attention to the metadata */
227 static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
229 (void)decoder, (void)metadata, (void)client_data;
231 printf("%d... ", mc_our_block_number_);
234 mc_our_block_number_++;
237 /* this version is used when we want to compare to our metadata copy */
238 static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
240 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
244 /* don't bother checking if we've already hit an error */
245 if(dcd->error_occurred)
248 printf("%d... ", mc_our_block_number_);
251 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
252 (void)die_("got more metadata blocks than expected");
253 dcd->error_occurred = true;
256 if(!compare_block_(our_metadata_.blocks[mc_our_block_number_], metadata)) {
257 (void)die_("metadata block mismatch");
258 dcd->error_occurred = true;
261 mc_our_block_number_++;
264 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
266 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
269 dcd->error_occurred = true;
270 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
273 static FLAC__bool generate_file_()
275 FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
276 FLAC__StreamMetadata *metadata[1];
278 printf("generating FLAC file for test\n");
280 while(our_metadata_.num_blocks > 0)
281 delete_from_our_metadata_(0);
283 streaminfo.is_last = false;
284 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
285 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
286 streaminfo.data.stream_info.min_blocksize = 576;
287 streaminfo.data.stream_info.max_blocksize = 576;
288 streaminfo.data.stream_info.min_framesize = 0;
289 streaminfo.data.stream_info.max_framesize = 0;
290 streaminfo.data.stream_info.sample_rate = 44100;
291 streaminfo.data.stream_info.channels = 1;
292 streaminfo.data.stream_info.bits_per_sample = 8;
293 streaminfo.data.stream_info.total_samples = 0;
294 memset(streaminfo.data.stream_info.md5sum, 0, 16);
297 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
298 vorbiscomment.is_last = false;
299 vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
300 vorbiscomment.length = (4 + vendor_string_length) + 4;
301 vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
302 vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length);
303 memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length);
304 vorbiscomment.data.vorbis_comment.num_comments = 0;
305 vorbiscomment.data.vorbis_comment.comments = 0;
308 padding.is_last = true;
309 padding.type = FLAC__METADATA_TYPE_PADDING;
310 padding.length = 1234;
312 metadata[0] = &padding;
315 !insert_to_our_metadata_(&streaminfo, 0, /*copy=*/true) ||
316 !insert_to_our_metadata_(&vorbiscomment, 1, /*copy=*/true) ||
317 !insert_to_our_metadata_(&padding, 2, /*copy=*/true)
319 return die_("priming our metadata");
321 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
322 return die_("creating the encoded file");
324 free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
329 static FLAC__bool test_file_(const char *filename, void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data))
331 FLAC__FileDecoder *decoder;
332 decoder_client_struct decoder_client_data;
334 FLAC__ASSERT(0 != filename);
335 FLAC__ASSERT(0 != metadata_callback);
337 mc_our_block_number_ = 0;
338 decoder_client_data.error_occurred = false;
340 printf("\ttesting '%s'... ", filename);
343 if(0 == (decoder = FLAC__file_decoder_new()))
344 return die_("couldn't allocate decoder instance");
346 FLAC__file_decoder_set_md5_checking(decoder, true);
347 FLAC__file_decoder_set_filename(decoder, filename);
348 FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
349 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
350 FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
351 FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
352 FLAC__file_decoder_set_metadata_respond_all(decoder);
353 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
354 FLAC__file_decoder_finish(decoder);
355 FLAC__file_decoder_delete(decoder);
356 return die_("initializing decoder\n");
358 if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
359 FLAC__file_decoder_finish(decoder);
360 FLAC__file_decoder_delete(decoder);
361 return die_("decoding file\n");
364 FLAC__file_decoder_finish(decoder);
365 FLAC__file_decoder_delete(decoder);
367 if(decoder_client_data.error_occurred)
370 if(mc_our_block_number_ != our_metadata_.num_blocks)
371 return die_("short metadata block count");
377 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
379 if(!file_utils__change_stats(filename, read_only))
380 return die_("during file_utils__change_stats()");
385 static FLAC__bool remove_file_(const char *filename)
387 while(our_metadata_.num_blocks > 0)
388 delete_from_our_metadata_(0);
390 if(!file_utils__remove_file(filename))
391 return die_("removing file");
396 static FLAC__bool test_level_0_()
398 FLAC__StreamMetadata streaminfo;
400 printf("\n\n++++++ testing level 0 interface\n");
402 if(!generate_file_())
405 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
408 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
409 return die_("during FLAC__metadata_get_streaminfo()");
411 /* check to see if some basic data matches (c.f. generate_file_()) */
412 if(streaminfo.data.stream_info.channels != 1)
413 return die_("mismatch in streaminfo.data.stream_info.channels");
414 if(streaminfo.data.stream_info.bits_per_sample != 8)
415 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
416 if(streaminfo.data.stream_info.sample_rate != 44100)
417 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
418 if(streaminfo.data.stream_info.min_blocksize != 576)
419 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
420 if(streaminfo.data.stream_info.max_blocksize != 576)
421 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
423 if(!remove_file_(flacfile_))
429 static FLAC__bool test_level_1_()
431 FLAC__Metadata_SimpleIterator *iterator;
432 FLAC__StreamMetadata *block, *app, *padding;
433 FLAC__byte data[1000];
434 unsigned our_current_position = 0;
436 printf("\n\n++++++ testing level 1 interface\n");
438 /************************************************************/
440 printf("simple iterator on read-only file\n");
442 if(!generate_file_())
445 if(!change_stats_(flacfile_, /*read_only=*/true))
448 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
451 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
452 return die_("FLAC__metadata_simple_iterator_new()");
454 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, false))
455 return die_("FLAC__metadata_simple_iterator_init() returned false");
457 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
458 if(FLAC__metadata_simple_iterator_is_writable(iterator))
459 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
461 printf("iterate forwards\n");
463 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
464 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
465 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
466 return die_("getting block 0");
467 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
468 return die_("expected STREAMINFO type");
470 return die_("expected is_last to be false");
471 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
472 return die_("bad STREAMINFO length");
473 /* check to see if some basic data matches (c.f. generate_file_()) */
474 if(block->data.stream_info.channels != 1)
475 return die_("mismatch in channels");
476 if(block->data.stream_info.bits_per_sample != 8)
477 return die_("mismatch in bits_per_sample");
478 if(block->data.stream_info.sample_rate != 44100)
479 return die_("mismatch in sample_rate");
480 if(block->data.stream_info.min_blocksize != 576)
481 return die_("mismatch in min_blocksize");
482 if(block->data.stream_info.max_blocksize != 576)
483 return die_("mismatch in max_blocksize");
485 if(!FLAC__metadata_simple_iterator_next(iterator))
486 return die_("forward iterator ended early");
487 our_current_position++;
489 if(!FLAC__metadata_simple_iterator_next(iterator))
490 return die_("forward iterator ended early");
491 our_current_position++;
493 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
494 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
495 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
496 return die_("getting block 2");
497 if(block->type != FLAC__METADATA_TYPE_PADDING)
498 return die_("expected PADDING type");
500 return die_("expected is_last to be true");
501 /* check to see if some basic data matches (c.f. generate_file_()) */
502 if(block->length != 1234)
503 return die_("bad PADDING length");
505 if(FLAC__metadata_simple_iterator_next(iterator))
506 return die_("forward iterator returned true but should have returned false");
508 printf("iterate backwards\n");
509 if(!FLAC__metadata_simple_iterator_prev(iterator))
510 return die_("reverse iterator ended early");
511 if(!FLAC__metadata_simple_iterator_prev(iterator))
512 return die_("reverse iterator ended early");
513 if(FLAC__metadata_simple_iterator_prev(iterator))
514 return die_("reverse iterator returned true but should have returned false");
516 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
518 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
519 printf("PASSED. FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
521 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
523 FLAC__metadata_simple_iterator_delete(iterator);
525 /************************************************************/
527 printf("simple iterator on writable file\n");
529 if(!change_stats_(flacfile_, /*read-only=*/false))
532 printf("creating APPLICATION block\n");
534 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
535 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
536 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
538 printf("creating PADDING block\n");
540 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
541 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
542 padding->length = 20;
544 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
545 return die_("FLAC__metadata_simple_iterator_new()");
547 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*preserve_file_stats=*/false))
548 return die_("FLAC__metadata_simple_iterator_init() returned false");
549 our_current_position = 0;
551 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
553 printf("[S]VP\ttry to write over STREAMINFO block...\n");
554 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
555 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
557 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
559 printf("[S]VP\tnext\n");
560 if(!FLAC__metadata_simple_iterator_next(iterator))
561 return die_("iterator ended early\n");
562 our_current_position++;
564 printf("S[V]P\tnext\n");
565 if(!FLAC__metadata_simple_iterator_next(iterator))
566 return die_("iterator ended early\n");
567 our_current_position++;
569 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
570 padding->length = 25;
571 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
572 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
573 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
576 printf("SVP[P]\tprev\n");
577 if(!FLAC__metadata_simple_iterator_prev(iterator))
578 return die_("iterator ended early\n");
579 our_current_position--;
581 printf("SV[P]P\tprev\n");
582 if(!FLAC__metadata_simple_iterator_prev(iterator))
583 return die_("iterator ended early\n");
584 our_current_position--;
586 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
587 padding->length = 30;
588 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
589 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
590 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
593 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
596 printf("SV[P]PP\tprev\n");
597 if(!FLAC__metadata_simple_iterator_prev(iterator))
598 return die_("iterator ended early\n");
599 our_current_position--;
601 printf("S[V]PPP\tprev\n");
602 if(!FLAC__metadata_simple_iterator_prev(iterator))
603 return die_("iterator ended early\n");
604 our_current_position--;
606 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
607 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
608 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
610 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
613 printf("[S]VPPP\tnext\n");
614 if(!FLAC__metadata_simple_iterator_next(iterator))
615 return die_("iterator ended early\n");
616 our_current_position++;
618 printf("S[V]PPP\tnext\n");
619 if(!FLAC__metadata_simple_iterator_next(iterator))
620 return die_("iterator ended early\n");
621 our_current_position++;
623 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
624 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
625 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
626 our_current_position--;
628 printf("S[V]PPP\tnext\n");
629 if(!FLAC__metadata_simple_iterator_next(iterator))
630 return die_("iterator ended early\n");
631 our_current_position++;
633 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
634 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
635 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
636 delete_from_our_metadata_(our_current_position--);
638 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
641 printf("S[V]PP\tnext\n");
642 if(!FLAC__metadata_simple_iterator_next(iterator))
643 return die_("iterator ended early\n");
644 our_current_position++;
646 printf("SV[P]P\tnext\n");
647 if(!FLAC__metadata_simple_iterator_next(iterator))
648 return die_("iterator ended early\n");
649 our_current_position++;
651 printf("SVP[P]\tdelete (last block), replace with padding\n");
652 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
653 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
654 our_current_position--;
656 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
659 printf("SV[P]P\tnext\n");
660 if(!FLAC__metadata_simple_iterator_next(iterator))
661 return die_("iterator ended early\n");
662 our_current_position++;
664 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
665 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
666 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
667 delete_from_our_metadata_(our_current_position--);
669 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
672 printf("SV[P]\tprev\n");
673 if(!FLAC__metadata_simple_iterator_prev(iterator))
674 return die_("iterator ended early\n");
675 our_current_position--;
677 printf("S[V]P\tprev\n");
678 if(!FLAC__metadata_simple_iterator_prev(iterator))
679 return die_("iterator ended early\n");
680 our_current_position--;
682 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
683 FLAC__ASSERT(our_current_position == 0);
684 block = FLAC__metadata_simple_iterator_get_block(iterator);
685 block->data.stream_info.sample_rate = 32000;
686 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
687 return die_("copying object");
688 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
689 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
690 FLAC__metadata_object_delete(block);
692 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
695 printf("[S]VP\tnext\n");
696 if(!FLAC__metadata_simple_iterator_next(iterator))
697 return die_("iterator ended early\n");
698 our_current_position++;
700 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
701 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
702 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
703 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
704 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
706 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
708 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
711 printf("SV[A]P\tnext\n");
712 if(!FLAC__metadata_simple_iterator_next(iterator))
713 return die_("iterator ended early\n");
714 our_current_position++;
716 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
717 app->data.application.id[0] = 'f'; /* twiddle the id */
718 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
719 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
720 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
722 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
724 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
727 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
728 app->data.application.id[0] = 'g'; /* twiddle the id */
729 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
730 return die_("setting APPLICATION data");
731 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
732 return die_("copying object");
733 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
734 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
736 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
739 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
740 app->data.application.id[0] = 'h'; /* twiddle the id */
741 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
742 return die_("setting APPLICATION data");
743 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
744 return die_("copying object");
745 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
746 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
748 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
751 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
752 app->data.application.id[0] = 'i'; /* twiddle the id */
753 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
754 return die_("setting APPLICATION data");
755 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
756 return die_("copying object");
757 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
758 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
759 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
761 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
764 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
765 app->data.application.id[0] = 'j'; /* twiddle the id */
766 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
767 return die_("setting APPLICATION data");
768 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
769 return die_("copying object");
770 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
771 return die_("copying object");
772 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
773 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
774 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
776 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
779 printf("SVA[A]PP\tnext\n");
780 if(!FLAC__metadata_simple_iterator_next(iterator))
781 return die_("iterator ended early\n");
782 our_current_position++;
784 printf("SVAA[P]P\tnext\n");
785 if(!FLAC__metadata_simple_iterator_next(iterator))
786 return die_("iterator ended early\n");
787 our_current_position++;
789 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
791 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
792 return die_("copying object");
793 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
794 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
796 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
799 printf("SVAAP[P]\tset APPLICATION (grow)\n");
800 app->data.application.id[0] = 'k'; /* twiddle the id */
801 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
802 return die_("copying object");
803 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
804 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
806 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
809 printf("SVAAP[A]\tset PADDING (equal)\n");
810 padding->length = 27;
811 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
812 return die_("copying object");
813 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
814 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
816 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
819 printf("SVAAP[P]\tprev\n");
820 if(!FLAC__metadata_simple_iterator_prev(iterator))
821 return die_("iterator ended early\n");
822 our_current_position--;
824 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
825 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
826 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
827 delete_from_our_metadata_(our_current_position--);
829 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
832 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
833 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
834 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
835 delete_from_our_metadata_(our_current_position--);
837 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
840 printf("SV[A]P\tnext\n");
841 if(!FLAC__metadata_simple_iterator_next(iterator))
842 return die_("iterator ended early\n");
843 our_current_position++;
845 printf("SVA[P]\tinsert PADDING after\n");
847 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
848 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
849 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
852 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
855 printf("SVAP[P]\tprev\n");
856 if(!FLAC__metadata_simple_iterator_prev(iterator))
857 return die_("iterator ended early\n");
858 our_current_position--;
860 printf("SVA[P]P\tprev\n");
861 if(!FLAC__metadata_simple_iterator_prev(iterator))
862 return die_("iterator ended early\n");
863 our_current_position--;
865 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
866 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
867 return die_("setting APPLICATION data");
868 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
869 return die_("copying object");
870 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
871 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
873 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
876 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
877 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
878 return die_("setting APPLICATION data");
879 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
880 return die_("copying object");
881 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
882 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
884 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
887 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
888 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
889 return die_("setting APPLICATION data");
890 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
891 return die_("copying object");
892 our_metadata_.blocks[our_current_position+1]->length = 0;
893 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
894 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
896 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
899 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
900 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
901 return die_("setting APPLICATION data");
902 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
903 return die_("copying object");
904 delete_from_our_metadata_(our_current_position+1);
905 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
906 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
908 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
911 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
912 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
913 return die_("setting APPLICATION data");
914 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
915 return die_("copying object");
916 delete_from_our_metadata_(our_current_position+1);
917 our_metadata_.blocks[our_current_position]->is_last = true;
918 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
919 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
921 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
924 printf("SV[A]\tset PADDING (equal size)\n");
925 padding->length = app->length;
926 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
927 return die_("copying object");
928 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
929 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
931 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
934 printf("SV[P]\tinsert PADDING after\n");
935 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
936 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
937 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
940 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
943 printf("SVP[P]\tinsert PADDING after\n");
945 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
946 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
947 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
950 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
953 printf("SVPP[P]\tprev\n");
954 if(!FLAC__metadata_simple_iterator_prev(iterator))
955 return die_("iterator ended early\n");
956 our_current_position--;
958 printf("SVP[P]P\tprev\n");
959 if(!FLAC__metadata_simple_iterator_prev(iterator))
960 return die_("iterator ended early\n");
961 our_current_position--;
963 printf("SV[P]PP\tprev\n");
964 if(!FLAC__metadata_simple_iterator_prev(iterator))
965 return die_("iterator ended early\n");
966 our_current_position--;
968 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
969 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
970 return die_("setting APPLICATION data");
971 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
972 return die_("copying object");
973 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
974 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
976 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
979 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
980 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
981 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
982 delete_from_our_metadata_(our_current_position--);
984 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
987 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
988 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
989 return die_("setting APPLICATION data");
990 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
991 return die_("copying object");
992 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
993 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
995 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
998 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
999 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1000 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1001 delete_from_our_metadata_(our_current_position--);
1003 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1006 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1007 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1008 return die_("setting APPLICATION data");
1009 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1010 return die_("copying object");
1011 delete_from_our_metadata_(our_current_position+1);
1012 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1013 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1015 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1018 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1019 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1020 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1021 delete_from_our_metadata_(our_current_position--);
1023 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1026 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1027 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1028 return die_("setting APPLICATION data");
1029 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1030 return die_("copying object");
1031 our_metadata_.blocks[our_current_position+1]->length = 0;
1032 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1033 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1035 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1038 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1039 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1040 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1041 delete_from_our_metadata_(our_current_position--);
1043 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1046 printf("S[V]PP\tnext\n");
1047 if(!FLAC__metadata_simple_iterator_next(iterator))
1048 return die_("iterator ended early\n");
1049 our_current_position++;
1051 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1052 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1053 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1054 delete_from_our_metadata_(our_current_position--);
1056 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1059 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1060 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1061 return die_("setting APPLICATION data");
1062 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1063 return die_("copying object");
1064 delete_from_our_metadata_(our_current_position+1);
1065 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1066 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1068 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1071 printf("delete simple iterator\n");
1073 FLAC__metadata_simple_iterator_delete(iterator);
1075 FLAC__metadata_object_delete(app);
1076 FLAC__metadata_object_delete(padding);
1078 if(!remove_file_(flacfile_))
1084 static FLAC__bool test_level_2_()
1086 FLAC__Metadata_Iterator *iterator;
1087 FLAC__Metadata_Chain *chain;
1088 FLAC__StreamMetadata *block, *app, *padding;
1089 FLAC__byte data[2000];
1090 unsigned our_current_position;
1092 printf("\n\n++++++ testing level 2 interface\n");
1094 printf("generate read-only file\n");
1096 if(!generate_file_())
1099 if(!change_stats_(flacfile_, /*read_only=*/true))
1102 printf("create chain\n");
1104 if(0 == (chain = FLAC__metadata_chain_new()))
1105 return die_("allocating chain");
1107 printf("read chain\n");
1109 if(!FLAC__metadata_chain_read(chain, flacfile_))
1110 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1112 printf("[S]VP\ttest initial metadata\n");
1114 if(!compare_chain_(chain, 0, 0))
1116 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1119 printf("switch file to read-write\n");
1121 if(!change_stats_(flacfile_, /*read-only=*/false))
1124 printf("create iterator\n");
1125 if(0 == (iterator = FLAC__metadata_iterator_new()))
1126 return die_("allocating memory for iterator");
1128 our_current_position = 0;
1130 FLAC__metadata_iterator_init(iterator, chain);
1132 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1133 return die_("getting block from iterator");
1135 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1137 printf("[S]VP\tmodify STREAMINFO, write\n");
1139 block->data.stream_info.sample_rate = 32000;
1140 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1141 return die_("copying object");
1143 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/true))
1144 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1145 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1147 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1150 printf("[S]VP\tnext\n");
1151 if(!FLAC__metadata_iterator_next(iterator))
1152 return die_("iterator ended early\n");
1153 our_current_position++;
1155 printf("S[V]P\tnext\n");
1156 if(!FLAC__metadata_iterator_next(iterator))
1157 return die_("iterator ended early\n");
1158 our_current_position++;
1160 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1161 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1162 return die_("getting block from iterator");
1163 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1164 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1165 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1166 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1167 return die_("setting APPLICATION data");
1168 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1169 return die_("copying object");
1170 if(!FLAC__metadata_iterator_set_block(iterator, app))
1171 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1173 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1174 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1175 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1177 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1180 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1181 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1182 return die_("copying object");
1183 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1184 return die_("setting APPLICATION data");
1185 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1186 return die_("copying object");
1187 if(!FLAC__metadata_iterator_set_block(iterator, app))
1188 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1190 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1191 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1192 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1194 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1197 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1198 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1199 return die_("copying object");
1200 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1201 return die_("setting APPLICATION data");
1202 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1203 return die_("copying object");
1204 if(!FLAC__metadata_iterator_set_block(iterator, app))
1205 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1207 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1208 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1209 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1211 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1214 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1215 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1216 return die_("copying object");
1217 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1218 return die_("setting APPLICATION data");
1219 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1220 return die_("copying object");
1221 if(!FLAC__metadata_iterator_set_block(iterator, app))
1222 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1224 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1225 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1226 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1228 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1231 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1232 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1233 return die_("copying object");
1234 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1235 return die_("setting APPLICATION data");
1236 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1237 return die_("copying object");
1238 if(!FLAC__metadata_iterator_set_block(iterator, app))
1239 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1241 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1242 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1243 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1245 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1248 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1249 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1250 return die_("creating PADDING block");
1251 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1252 return die_("copying object");
1253 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1254 return die_("setting APPLICATION data");
1255 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1256 return die_("copying object");
1257 padding->length = 0;
1258 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1259 return die_("internal error");
1260 if(!FLAC__metadata_iterator_set_block(iterator, app))
1261 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1263 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1264 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1265 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1267 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1270 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1271 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1272 return die_("copying object");
1273 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1274 return die_("setting APPLICATION data");
1275 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1276 return die_("copying object");
1277 our_metadata_.blocks[our_current_position+1]->length = 13;
1278 if(!FLAC__metadata_iterator_set_block(iterator, app))
1279 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1281 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1282 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1283 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1285 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1288 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1289 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1290 return die_("copying object");
1291 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1292 return die_("setting APPLICATION data");
1293 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1294 return die_("copying object");
1295 if(!FLAC__metadata_iterator_set_block(iterator, app))
1296 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1298 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1299 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1300 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1302 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1305 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1306 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1307 return die_("copying object");
1308 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1309 return die_("setting APPLICATION data");
1310 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1311 return die_("copying object");
1312 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1313 if(!FLAC__metadata_iterator_set_block(iterator, app))
1314 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1316 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1317 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1318 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1320 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1323 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1324 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1325 return die_("copying object");
1326 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1327 return die_("setting APPLICATION data");
1328 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1329 return die_("copying object");
1330 delete_from_our_metadata_(our_current_position+1);
1331 if(!FLAC__metadata_iterator_set_block(iterator, app))
1332 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1334 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1335 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1336 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1338 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1341 printf("SV[A]\tprev\n");
1342 if(!FLAC__metadata_iterator_prev(iterator))
1343 return die_("iterator ended early\n");
1344 our_current_position--;
1346 printf("S[V]A\tprev\n");
1347 if(!FLAC__metadata_iterator_prev(iterator))
1348 return die_("iterator ended early\n");
1349 our_current_position--;
1351 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1352 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1353 return die_("creating PADDING block");
1354 padding->length = 30;
1355 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1356 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1358 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1360 printf("[S]VP\tnext\n");
1361 if(!FLAC__metadata_iterator_next(iterator))
1362 return die_("iterator ended early\n");
1363 our_current_position++;
1365 printf("S[V]A\tinsert PADDING after\n");
1366 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1367 return die_("copying metadata");
1368 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1369 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1371 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1374 printf("SV[P]A\tinsert PADDING before\n");
1375 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1376 return die_("creating PADDING block");
1377 padding->length = 17;
1378 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1379 return die_("copying metadata");
1380 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1381 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1383 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1386 printf("SV[P]PA\tinsert PADDING before\n");
1387 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1388 return die_("creating PADDING block");
1389 padding->length = 0;
1390 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1391 return die_("copying metadata");
1392 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1393 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1395 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1398 printf("SV[P]PPA\tnext\n");
1399 if(!FLAC__metadata_iterator_next(iterator))
1400 return die_("iterator ended early\n");
1401 our_current_position++;
1403 printf("SVP[P]PA\tnext\n");
1404 if(!FLAC__metadata_iterator_next(iterator))
1405 return die_("iterator ended early\n");
1406 our_current_position++;
1408 printf("SVPP[P]A\tnext\n");
1409 if(!FLAC__metadata_iterator_next(iterator))
1410 return die_("iterator ended early\n");
1411 our_current_position++;
1413 printf("SVPPP[A]\tinsert PADDING after\n");
1414 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1415 return die_("creating PADDING block");
1416 padding->length = 57;
1417 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1418 return die_("copying metadata");
1419 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1420 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1422 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1425 printf("SVPPPA[P]\tinsert PADDING before\n");
1426 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1427 return die_("creating PADDING block");
1428 padding->length = 99;
1429 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1430 return die_("copying metadata");
1431 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1432 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1434 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1437 printf("delete iterator\n");
1438 FLAC__metadata_iterator_delete(iterator);
1439 our_current_position = 0;
1441 printf("SVPPPAPP\tmerge padding\n");
1442 FLAC__metadata_chain_merge_padding(chain);
1443 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1444 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1445 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1446 delete_from_our_metadata_(7);
1447 delete_from_our_metadata_(4);
1448 delete_from_our_metadata_(3);
1450 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1451 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1452 if(!compare_chain_(chain, 0, 0))
1454 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1457 printf("SVPAP\tsort padding\n");
1458 FLAC__metadata_chain_sort_padding(chain);
1459 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1460 delete_from_our_metadata_(2);
1462 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1463 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1464 if(!compare_chain_(chain, 0, 0))
1466 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1469 printf("create iterator\n");
1470 if(0 == (iterator = FLAC__metadata_iterator_new()))
1471 return die_("allocating memory for iterator");
1473 our_current_position = 0;
1475 FLAC__metadata_iterator_init(iterator, chain);
1477 printf("[S]VAP\tnext\n");
1478 if(!FLAC__metadata_iterator_next(iterator))
1479 return die_("iterator ended early\n");
1480 our_current_position++;
1482 printf("S[V]AP\tnext\n");
1483 if(!FLAC__metadata_iterator_next(iterator))
1484 return die_("iterator ended early\n");
1485 our_current_position++;
1487 printf("SV[A]P\tdelete middle block, replace with padding\n");
1488 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1489 return die_("creating PADDING block");
1490 padding->length = 71;
1491 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1492 return die_("copying object");
1493 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1494 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1496 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1499 printf("S[V]PP\tnext\n");
1500 if(!FLAC__metadata_iterator_next(iterator))
1501 return die_("iterator ended early\n");
1502 our_current_position++;
1504 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1505 delete_from_our_metadata_(our_current_position--);
1506 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1507 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1509 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1512 printf("S[V]P\tnext\n");
1513 if(!FLAC__metadata_iterator_next(iterator))
1514 return die_("iterator ended early\n");
1515 our_current_position++;
1517 printf("SV[P]\tdelete last block, replace with padding\n");
1518 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1519 return die_("creating PADDING block");
1520 padding->length = 219;
1521 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1522 return die_("copying object");
1523 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1524 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1526 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1529 printf("S[V]P\tnext\n");
1530 if(!FLAC__metadata_iterator_next(iterator))
1531 return die_("iterator ended early\n");
1532 our_current_position++;
1534 printf("SV[P]\tdelete last block, don't replace with padding\n");
1535 delete_from_our_metadata_(our_current_position--);
1536 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1537 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1539 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1542 printf("S[V]\tprev\n");
1543 if(!FLAC__metadata_iterator_prev(iterator))
1544 return die_("iterator ended early\n");
1545 our_current_position--;
1547 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1548 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1549 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1551 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1554 printf("delete iterator\n");
1555 FLAC__metadata_iterator_delete(iterator);
1556 our_current_position = 0;
1558 printf("SV\tmerge padding\n");
1559 FLAC__metadata_chain_merge_padding(chain);
1561 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1562 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1563 if(!compare_chain_(chain, 0, 0))
1565 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1568 printf("SV\tsort padding\n");
1569 FLAC__metadata_chain_sort_padding(chain);
1571 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1572 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1573 if(!compare_chain_(chain, 0, 0))
1575 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1578 printf("delete chain\n");
1580 FLAC__metadata_chain_delete(chain);
1582 if(!remove_file_(flacfile_))
1588 FLAC__bool test_metadata_file_manipulation()
1590 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1592 our_metadata_.num_blocks = 0;
1594 if(!test_level_0_())
1597 if(!test_level_1_())
1600 if(!test_level_2_())