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 /* initialize 'data' to avoid Valgrind errors */
438 memset(data, 0, sizeof(data));
440 printf("\n\n++++++ testing level 1 interface\n");
442 /************************************************************/
444 printf("simple iterator on read-only file\n");
446 if(!generate_file_())
449 if(!change_stats_(flacfile_, /*read_only=*/true))
452 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
455 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
456 return die_("FLAC__metadata_simple_iterator_new()");
458 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
459 return die_("FLAC__metadata_simple_iterator_init() returned false");
461 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
462 if(FLAC__metadata_simple_iterator_is_writable(iterator))
463 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
465 printf("iterate forwards\n");
467 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
468 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
469 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
470 return die_("getting block 0");
471 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
472 return die_("expected STREAMINFO type");
474 return die_("expected is_last to be false");
475 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
476 return die_("bad STREAMINFO length");
477 /* check to see if some basic data matches (c.f. generate_file_()) */
478 if(block->data.stream_info.channels != 1)
479 return die_("mismatch in channels");
480 if(block->data.stream_info.bits_per_sample != 8)
481 return die_("mismatch in bits_per_sample");
482 if(block->data.stream_info.sample_rate != 44100)
483 return die_("mismatch in sample_rate");
484 if(block->data.stream_info.min_blocksize != 576)
485 return die_("mismatch in min_blocksize");
486 if(block->data.stream_info.max_blocksize != 576)
487 return die_("mismatch in max_blocksize");
488 FLAC__metadata_object_delete(block);
490 if(!FLAC__metadata_simple_iterator_next(iterator))
491 return die_("forward iterator ended early");
492 our_current_position++;
494 if(!FLAC__metadata_simple_iterator_next(iterator))
495 return die_("forward iterator ended early");
496 our_current_position++;
498 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
499 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
500 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
501 return die_("getting block 2");
502 if(block->type != FLAC__METADATA_TYPE_PADDING)
503 return die_("expected PADDING type");
505 return die_("expected is_last to be true");
506 /* check to see if some basic data matches (c.f. generate_file_()) */
507 if(block->length != 1234)
508 return die_("bad PADDING length");
509 FLAC__metadata_object_delete(block);
511 if(FLAC__metadata_simple_iterator_next(iterator))
512 return die_("forward iterator returned true but should have returned false");
514 printf("iterate backwards\n");
515 if(!FLAC__metadata_simple_iterator_prev(iterator))
516 return die_("reverse iterator ended early");
517 if(!FLAC__metadata_simple_iterator_prev(iterator))
518 return die_("reverse iterator ended early");
519 if(FLAC__metadata_simple_iterator_prev(iterator))
520 return die_("reverse iterator returned true but should have returned false");
522 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
524 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
525 printf("PASSED. FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
527 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
529 FLAC__metadata_simple_iterator_delete(iterator);
531 /************************************************************/
533 printf("simple iterator on writable file\n");
535 if(!change_stats_(flacfile_, /*read-only=*/false))
538 printf("creating APPLICATION block\n");
540 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
541 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
542 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
544 printf("creating PADDING block\n");
546 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
547 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
548 padding->length = 20;
550 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
551 return die_("FLAC__metadata_simple_iterator_new()");
553 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
554 return die_("FLAC__metadata_simple_iterator_init() returned false");
555 our_current_position = 0;
557 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
559 printf("[S]VP\ttry to write over STREAMINFO block...\n");
560 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
561 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
563 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
565 printf("[S]VP\tnext\n");
566 if(!FLAC__metadata_simple_iterator_next(iterator))
567 return die_("iterator ended early\n");
568 our_current_position++;
570 printf("S[V]P\tnext\n");
571 if(!FLAC__metadata_simple_iterator_next(iterator))
572 return die_("iterator ended early\n");
573 our_current_position++;
575 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
576 padding->length = 25;
577 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
578 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
579 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
582 printf("SVP[P]\tprev\n");
583 if(!FLAC__metadata_simple_iterator_prev(iterator))
584 return die_("iterator ended early\n");
585 our_current_position--;
587 printf("SV[P]P\tprev\n");
588 if(!FLAC__metadata_simple_iterator_prev(iterator))
589 return die_("iterator ended early\n");
590 our_current_position--;
592 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
593 padding->length = 30;
594 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
595 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
596 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
599 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
602 printf("SV[P]PP\tprev\n");
603 if(!FLAC__metadata_simple_iterator_prev(iterator))
604 return die_("iterator ended early\n");
605 our_current_position--;
607 printf("S[V]PPP\tprev\n");
608 if(!FLAC__metadata_simple_iterator_prev(iterator))
609 return die_("iterator ended early\n");
610 our_current_position--;
612 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
613 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
614 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
616 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
619 printf("[S]VPPP\tnext\n");
620 if(!FLAC__metadata_simple_iterator_next(iterator))
621 return die_("iterator ended early\n");
622 our_current_position++;
624 printf("S[V]PPP\tnext\n");
625 if(!FLAC__metadata_simple_iterator_next(iterator))
626 return die_("iterator ended early\n");
627 our_current_position++;
629 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
630 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
631 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
632 our_current_position--;
634 printf("S[V]PPP\tnext\n");
635 if(!FLAC__metadata_simple_iterator_next(iterator))
636 return die_("iterator ended early\n");
637 our_current_position++;
639 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
640 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
641 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
642 delete_from_our_metadata_(our_current_position--);
644 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
647 printf("S[V]PP\tnext\n");
648 if(!FLAC__metadata_simple_iterator_next(iterator))
649 return die_("iterator ended early\n");
650 our_current_position++;
652 printf("SV[P]P\tnext\n");
653 if(!FLAC__metadata_simple_iterator_next(iterator))
654 return die_("iterator ended early\n");
655 our_current_position++;
657 printf("SVP[P]\tdelete (last block), replace with padding\n");
658 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
659 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
660 our_current_position--;
662 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
665 printf("SV[P]P\tnext\n");
666 if(!FLAC__metadata_simple_iterator_next(iterator))
667 return die_("iterator ended early\n");
668 our_current_position++;
670 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
671 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
672 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
673 delete_from_our_metadata_(our_current_position--);
675 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
678 printf("SV[P]\tprev\n");
679 if(!FLAC__metadata_simple_iterator_prev(iterator))
680 return die_("iterator ended early\n");
681 our_current_position--;
683 printf("S[V]P\tprev\n");
684 if(!FLAC__metadata_simple_iterator_prev(iterator))
685 return die_("iterator ended early\n");
686 our_current_position--;
688 printf("[S]VP\tset STREAMINFO (change sample rate)\n");
689 FLAC__ASSERT(our_current_position == 0);
690 block = FLAC__metadata_simple_iterator_get_block(iterator);
691 block->data.stream_info.sample_rate = 32000;
692 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
693 return die_("copying object");
694 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
695 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
696 FLAC__metadata_object_delete(block);
698 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
701 printf("[S]VP\tnext\n");
702 if(!FLAC__metadata_simple_iterator_next(iterator))
703 return die_("iterator ended early\n");
704 our_current_position++;
706 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
707 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
708 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
709 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
710 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
712 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
714 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
717 printf("SV[A]P\tnext\n");
718 if(!FLAC__metadata_simple_iterator_next(iterator))
719 return die_("iterator ended early\n");
720 our_current_position++;
722 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
723 app->data.application.id[0] = 'f'; /* twiddle the id */
724 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
725 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
726 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
728 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
730 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
733 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
734 app->data.application.id[0] = 'g'; /* twiddle the id */
735 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
736 return die_("setting APPLICATION data");
737 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
738 return die_("copying object");
739 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
740 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
742 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
745 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
746 app->data.application.id[0] = 'h'; /* twiddle the id */
747 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
748 return die_("setting APPLICATION data");
749 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
750 return die_("copying object");
751 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
752 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
754 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
757 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
758 app->data.application.id[0] = 'i'; /* twiddle the id */
759 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
760 return die_("setting APPLICATION data");
761 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
762 return die_("copying object");
763 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
764 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
765 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
767 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
770 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
771 app->data.application.id[0] = 'j'; /* twiddle the id */
772 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
773 return die_("setting APPLICATION data");
774 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
775 return die_("copying object");
776 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
777 return die_("copying object");
778 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
779 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
780 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
782 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
785 printf("SVA[A]PP\tnext\n");
786 if(!FLAC__metadata_simple_iterator_next(iterator))
787 return die_("iterator ended early\n");
788 our_current_position++;
790 printf("SVAA[P]P\tnext\n");
791 if(!FLAC__metadata_simple_iterator_next(iterator))
792 return die_("iterator ended early\n");
793 our_current_position++;
795 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
797 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
798 return die_("copying object");
799 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
800 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
802 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
805 printf("SVAAP[P]\tset APPLICATION (grow)\n");
806 app->data.application.id[0] = 'k'; /* twiddle the id */
807 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
808 return die_("copying object");
809 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
810 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
812 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
815 printf("SVAAP[A]\tset PADDING (equal)\n");
816 padding->length = 27;
817 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
818 return die_("copying object");
819 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
820 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
822 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
825 printf("SVAAP[P]\tprev\n");
826 if(!FLAC__metadata_simple_iterator_prev(iterator))
827 return die_("iterator ended early\n");
828 our_current_position--;
830 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
831 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
832 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
833 delete_from_our_metadata_(our_current_position--);
835 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
838 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
839 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
840 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
841 delete_from_our_metadata_(our_current_position--);
843 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
846 printf("SV[A]P\tnext\n");
847 if(!FLAC__metadata_simple_iterator_next(iterator))
848 return die_("iterator ended early\n");
849 our_current_position++;
851 printf("SVA[P]\tinsert PADDING after\n");
853 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
854 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
855 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
858 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
861 printf("SVAP[P]\tprev\n");
862 if(!FLAC__metadata_simple_iterator_prev(iterator))
863 return die_("iterator ended early\n");
864 our_current_position--;
866 printf("SVA[P]P\tprev\n");
867 if(!FLAC__metadata_simple_iterator_prev(iterator))
868 return die_("iterator ended early\n");
869 our_current_position--;
871 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
872 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
873 return die_("setting APPLICATION data");
874 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
875 return die_("copying object");
876 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
877 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
879 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
882 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
883 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
884 return die_("setting APPLICATION data");
885 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
886 return die_("copying object");
887 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
888 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
890 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
893 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
894 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
895 return die_("setting APPLICATION data");
896 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
897 return die_("copying object");
898 our_metadata_.blocks[our_current_position+1]->length = 0;
899 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
900 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
902 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
905 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
906 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
907 return die_("setting APPLICATION data");
908 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
909 return die_("copying object");
910 delete_from_our_metadata_(our_current_position+1);
911 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
912 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
914 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
917 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
918 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
919 return die_("setting APPLICATION data");
920 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
921 return die_("copying object");
922 delete_from_our_metadata_(our_current_position+1);
923 our_metadata_.blocks[our_current_position]->is_last = true;
924 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
925 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
927 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
930 printf("SV[A]\tset PADDING (equal size)\n");
931 padding->length = app->length;
932 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
933 return die_("copying object");
934 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
935 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
937 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
940 printf("SV[P]\tinsert PADDING after\n");
941 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
942 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
943 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
946 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
949 printf("SVP[P]\tinsert PADDING after\n");
951 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
952 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
953 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
956 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
959 printf("SVPP[P]\tprev\n");
960 if(!FLAC__metadata_simple_iterator_prev(iterator))
961 return die_("iterator ended early\n");
962 our_current_position--;
964 printf("SVP[P]P\tprev\n");
965 if(!FLAC__metadata_simple_iterator_prev(iterator))
966 return die_("iterator ended early\n");
967 our_current_position--;
969 printf("SV[P]PP\tprev\n");
970 if(!FLAC__metadata_simple_iterator_prev(iterator))
971 return die_("iterator ended early\n");
972 our_current_position--;
974 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
975 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
976 return die_("setting APPLICATION data");
977 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
978 return die_("copying object");
979 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
980 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
982 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
985 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
986 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
987 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
988 delete_from_our_metadata_(our_current_position--);
990 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
993 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
994 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
995 return die_("setting APPLICATION data");
996 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
997 return die_("copying object");
998 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
999 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1001 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1004 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1005 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1006 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1007 delete_from_our_metadata_(our_current_position--);
1009 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1012 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1013 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1014 return die_("setting APPLICATION data");
1015 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1016 return die_("copying object");
1017 delete_from_our_metadata_(our_current_position+1);
1018 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1019 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1021 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1024 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1025 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1026 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1027 delete_from_our_metadata_(our_current_position--);
1029 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1032 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1033 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1034 return die_("setting APPLICATION data");
1035 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1036 return die_("copying object");
1037 our_metadata_.blocks[our_current_position+1]->length = 0;
1038 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1039 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1041 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1044 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1045 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1046 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1047 delete_from_our_metadata_(our_current_position--);
1049 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1052 printf("S[V]PP\tnext\n");
1053 if(!FLAC__metadata_simple_iterator_next(iterator))
1054 return die_("iterator ended early\n");
1055 our_current_position++;
1057 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1058 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1059 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1060 delete_from_our_metadata_(our_current_position--);
1062 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1065 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1066 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1067 return die_("setting APPLICATION data");
1068 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1069 return die_("copying object");
1070 delete_from_our_metadata_(our_current_position+1);
1071 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1072 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1074 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1077 printf("delete simple iterator\n");
1079 FLAC__metadata_simple_iterator_delete(iterator);
1081 FLAC__metadata_object_delete(app);
1082 FLAC__metadata_object_delete(padding);
1084 if(!remove_file_(flacfile_))
1090 static FLAC__bool test_level_2_()
1092 FLAC__Metadata_Iterator *iterator;
1093 FLAC__Metadata_Chain *chain;
1094 FLAC__StreamMetadata *block, *app, *padding;
1095 FLAC__byte data[2000];
1096 unsigned our_current_position;
1098 /* initialize 'data' to avoid Valgrind errors */
1099 memset(data, 0, sizeof(data));
1101 printf("\n\n++++++ testing level 2 interface\n");
1103 printf("generate read-only file\n");
1105 if(!generate_file_())
1108 if(!change_stats_(flacfile_, /*read_only=*/true))
1111 printf("create chain\n");
1113 if(0 == (chain = FLAC__metadata_chain_new()))
1114 return die_("allocating chain");
1116 printf("read chain\n");
1118 if(!FLAC__metadata_chain_read(chain, flacfile_))
1119 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1121 printf("[S]VP\ttest initial metadata\n");
1123 if(!compare_chain_(chain, 0, 0))
1125 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1128 printf("switch file to read-write\n");
1130 if(!change_stats_(flacfile_, /*read-only=*/false))
1133 printf("create iterator\n");
1134 if(0 == (iterator = FLAC__metadata_iterator_new()))
1135 return die_("allocating memory for iterator");
1137 our_current_position = 0;
1139 FLAC__metadata_iterator_init(iterator, chain);
1141 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1142 return die_("getting block from iterator");
1144 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1146 printf("[S]VP\tmodify STREAMINFO, write\n");
1148 block->data.stream_info.sample_rate = 32000;
1149 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1150 return die_("copying object");
1152 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/true))
1153 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1154 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1156 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1159 printf("[S]VP\tnext\n");
1160 if(!FLAC__metadata_iterator_next(iterator))
1161 return die_("iterator ended early\n");
1162 our_current_position++;
1164 printf("S[V]P\tnext\n");
1165 if(!FLAC__metadata_iterator_next(iterator))
1166 return die_("iterator ended early\n");
1167 our_current_position++;
1169 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1170 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1171 return die_("getting block from iterator");
1172 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1173 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1174 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1175 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1176 return die_("setting APPLICATION data");
1177 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1178 return die_("copying object");
1179 if(!FLAC__metadata_iterator_set_block(iterator, app))
1180 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1182 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1183 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1184 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1186 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1189 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1190 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1191 return die_("copying object");
1192 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1193 return die_("setting APPLICATION data");
1194 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1195 return die_("copying object");
1196 if(!FLAC__metadata_iterator_set_block(iterator, app))
1197 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1199 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1200 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1201 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1203 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1206 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1207 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1208 return die_("copying object");
1209 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1210 return die_("setting APPLICATION data");
1211 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1212 return die_("copying object");
1213 if(!FLAC__metadata_iterator_set_block(iterator, app))
1214 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1216 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1217 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1218 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1220 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1223 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1224 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1225 return die_("copying object");
1226 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1227 return die_("setting APPLICATION data");
1228 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1229 return die_("copying object");
1230 if(!FLAC__metadata_iterator_set_block(iterator, app))
1231 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1233 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1234 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1235 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1237 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1240 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1241 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1242 return die_("copying object");
1243 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1244 return die_("setting APPLICATION data");
1245 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1246 return die_("copying object");
1247 if(!FLAC__metadata_iterator_set_block(iterator, app))
1248 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1250 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1251 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1252 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1254 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1257 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1258 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1259 return die_("creating PADDING block");
1260 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1261 return die_("copying object");
1262 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1263 return die_("setting APPLICATION data");
1264 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1265 return die_("copying object");
1266 padding->length = 0;
1267 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1268 return die_("internal error");
1269 if(!FLAC__metadata_iterator_set_block(iterator, app))
1270 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1272 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1273 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1274 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1276 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1279 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1280 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1281 return die_("copying object");
1282 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1283 return die_("setting APPLICATION data");
1284 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1285 return die_("copying object");
1286 our_metadata_.blocks[our_current_position+1]->length = 13;
1287 if(!FLAC__metadata_iterator_set_block(iterator, app))
1288 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1290 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1291 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1292 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1294 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1297 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1298 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1299 return die_("copying object");
1300 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1301 return die_("setting APPLICATION data");
1302 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1303 return die_("copying object");
1304 if(!FLAC__metadata_iterator_set_block(iterator, app))
1305 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1307 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1308 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1309 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1311 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1314 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1315 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1316 return die_("copying object");
1317 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1318 return die_("setting APPLICATION data");
1319 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1320 return die_("copying object");
1321 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1322 if(!FLAC__metadata_iterator_set_block(iterator, app))
1323 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1325 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1326 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1327 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1329 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1332 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1333 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1334 return die_("copying object");
1335 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1336 return die_("setting APPLICATION data");
1337 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1338 return die_("copying object");
1339 delete_from_our_metadata_(our_current_position+1);
1340 if(!FLAC__metadata_iterator_set_block(iterator, app))
1341 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1343 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1344 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1345 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1347 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1350 printf("SV[A]\tprev\n");
1351 if(!FLAC__metadata_iterator_prev(iterator))
1352 return die_("iterator ended early\n");
1353 our_current_position--;
1355 printf("S[V]A\tprev\n");
1356 if(!FLAC__metadata_iterator_prev(iterator))
1357 return die_("iterator ended early\n");
1358 our_current_position--;
1360 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1361 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1362 return die_("creating PADDING block");
1363 padding->length = 30;
1364 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1365 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1367 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1369 printf("[S]VP\tnext\n");
1370 if(!FLAC__metadata_iterator_next(iterator))
1371 return die_("iterator ended early\n");
1372 our_current_position++;
1374 printf("S[V]A\tinsert PADDING after\n");
1375 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1376 return die_("copying metadata");
1377 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1378 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1380 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1383 printf("SV[P]A\tinsert PADDING before\n");
1384 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1385 return die_("creating PADDING block");
1386 padding->length = 17;
1387 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1388 return die_("copying metadata");
1389 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1390 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1392 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1395 printf("SV[P]PA\tinsert PADDING before\n");
1396 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1397 return die_("creating PADDING block");
1398 padding->length = 0;
1399 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1400 return die_("copying metadata");
1401 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1402 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1404 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1407 printf("SV[P]PPA\tnext\n");
1408 if(!FLAC__metadata_iterator_next(iterator))
1409 return die_("iterator ended early\n");
1410 our_current_position++;
1412 printf("SVP[P]PA\tnext\n");
1413 if(!FLAC__metadata_iterator_next(iterator))
1414 return die_("iterator ended early\n");
1415 our_current_position++;
1417 printf("SVPP[P]A\tnext\n");
1418 if(!FLAC__metadata_iterator_next(iterator))
1419 return die_("iterator ended early\n");
1420 our_current_position++;
1422 printf("SVPPP[A]\tinsert PADDING after\n");
1423 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1424 return die_("creating PADDING block");
1425 padding->length = 57;
1426 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1427 return die_("copying metadata");
1428 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1429 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1431 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1434 printf("SVPPPA[P]\tinsert PADDING before\n");
1435 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1436 return die_("creating PADDING block");
1437 padding->length = 99;
1438 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1439 return die_("copying metadata");
1440 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1441 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1443 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1446 printf("delete iterator\n");
1447 FLAC__metadata_iterator_delete(iterator);
1448 our_current_position = 0;
1450 printf("SVPPPAPP\tmerge padding\n");
1451 FLAC__metadata_chain_merge_padding(chain);
1452 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1453 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1454 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1455 delete_from_our_metadata_(7);
1456 delete_from_our_metadata_(4);
1457 delete_from_our_metadata_(3);
1459 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1460 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1461 if(!compare_chain_(chain, 0, 0))
1463 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1466 printf("SVPAP\tsort padding\n");
1467 FLAC__metadata_chain_sort_padding(chain);
1468 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1469 delete_from_our_metadata_(2);
1471 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1472 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1473 if(!compare_chain_(chain, 0, 0))
1475 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1478 printf("create iterator\n");
1479 if(0 == (iterator = FLAC__metadata_iterator_new()))
1480 return die_("allocating memory for iterator");
1482 our_current_position = 0;
1484 FLAC__metadata_iterator_init(iterator, chain);
1486 printf("[S]VAP\tnext\n");
1487 if(!FLAC__metadata_iterator_next(iterator))
1488 return die_("iterator ended early\n");
1489 our_current_position++;
1491 printf("S[V]AP\tnext\n");
1492 if(!FLAC__metadata_iterator_next(iterator))
1493 return die_("iterator ended early\n");
1494 our_current_position++;
1496 printf("SV[A]P\tdelete middle block, replace with padding\n");
1497 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1498 return die_("creating PADDING block");
1499 padding->length = 71;
1500 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1501 return die_("copying object");
1502 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1503 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1505 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1508 printf("S[V]PP\tnext\n");
1509 if(!FLAC__metadata_iterator_next(iterator))
1510 return die_("iterator ended early\n");
1511 our_current_position++;
1513 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1514 delete_from_our_metadata_(our_current_position--);
1515 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1516 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1518 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1521 printf("S[V]P\tnext\n");
1522 if(!FLAC__metadata_iterator_next(iterator))
1523 return die_("iterator ended early\n");
1524 our_current_position++;
1526 printf("SV[P]\tdelete last block, replace with padding\n");
1527 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1528 return die_("creating PADDING block");
1529 padding->length = 219;
1530 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1531 return die_("copying object");
1532 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1533 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1535 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1538 printf("S[V]P\tnext\n");
1539 if(!FLAC__metadata_iterator_next(iterator))
1540 return die_("iterator ended early\n");
1541 our_current_position++;
1543 printf("SV[P]\tdelete last block, don't replace with padding\n");
1544 delete_from_our_metadata_(our_current_position--);
1545 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1546 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1548 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1551 printf("S[V]\tprev\n");
1552 if(!FLAC__metadata_iterator_prev(iterator))
1553 return die_("iterator ended early\n");
1554 our_current_position--;
1556 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1557 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1558 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1560 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1563 printf("delete iterator\n");
1564 FLAC__metadata_iterator_delete(iterator);
1565 our_current_position = 0;
1567 printf("SV\tmerge padding\n");
1568 FLAC__metadata_chain_merge_padding(chain);
1570 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1571 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1572 if(!compare_chain_(chain, 0, 0))
1574 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1577 printf("SV\tsort padding\n");
1578 FLAC__metadata_chain_sort_padding(chain);
1580 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1581 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1582 if(!compare_chain_(chain, 0, 0))
1584 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1587 printf("delete chain\n");
1589 FLAC__metadata_chain_delete(chain);
1591 if(!remove_file_(flacfile_))
1597 FLAC__bool test_metadata_file_manipulation()
1599 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1601 our_metadata_.num_blocks = 0;
1603 if(!test_level_0_())
1606 if(!test_level_1_())
1609 if(!test_level_2_())