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/file_utils.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(!FLAC__file_utils_change_stats(filename, read_only))
381 return die_("during FLAC__file_utils_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(!FLAC__file_utils_remove_file(filename))
392 return die_("removing file");
397 static FLAC__bool test_level_0_()
399 FLAC__StreamMetadata streaminfo;
401 printf("\n\n++++++ testing level 0 interface\n");
403 if(!generate_file_())
406 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
409 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
410 return die_("during FLAC__metadata_get_streaminfo()");
412 /* check to see if some basic data matches (c.f. generate_file_()) */
413 if(streaminfo.data.stream_info.channels != 1)
414 return die_("mismatch in streaminfo.data.stream_info.channels");
415 if(streaminfo.data.stream_info.bits_per_sample != 8)
416 return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
417 if(streaminfo.data.stream_info.sample_rate != 44100)
418 return die_("mismatch in streaminfo.data.stream_info.sample_rate");
419 if(streaminfo.data.stream_info.min_blocksize != 576)
420 return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
421 if(streaminfo.data.stream_info.max_blocksize != 576)
422 return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
424 if(!remove_file_(flacfile_))
430 static FLAC__bool test_level_1_()
432 FLAC__Metadata_SimpleIterator *iterator;
433 FLAC__StreamMetadata *block, *app, *padding;
434 FLAC__byte data[1000];
435 unsigned our_current_position = 0;
437 printf("\n\n++++++ testing level 1 interface\n");
439 /************************************************************/
441 printf("simple iterator on read-only file\n");
443 if(!generate_file_())
446 if(!change_stats_(flacfile_, /*read_only=*/true))
449 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
452 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
453 return die_("FLAC__metadata_simple_iterator_new()");
455 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
456 return die_("FLAC__metadata_simple_iterator_init() returned false");
458 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
459 if(FLAC__metadata_simple_iterator_is_writable(iterator))
460 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
462 printf("iterate forwards\n");
464 if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
465 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
466 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
467 return die_("getting block 0");
468 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
469 return die_("expected STREAMINFO type");
471 return die_("expected is_last to be false");
472 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
473 return die_("bad STREAMINFO length");
474 /* check to see if some basic data matches (c.f. generate_file_()) */
475 if(block->data.stream_info.channels != 1)
476 return die_("mismatch in channels");
477 if(block->data.stream_info.bits_per_sample != 8)
478 return die_("mismatch in bits_per_sample");
479 if(block->data.stream_info.sample_rate != 44100)
480 return die_("mismatch in sample_rate");
481 if(block->data.stream_info.min_blocksize != 576)
482 return die_("mismatch in min_blocksize");
483 if(block->data.stream_info.max_blocksize != 576)
484 return die_("mismatch in max_blocksize");
486 if(!FLAC__metadata_simple_iterator_next(iterator))
487 return die_("forward iterator ended early");
488 our_current_position++;
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_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
495 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
496 if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
497 return die_("getting block 2");
498 if(block->type != FLAC__METADATA_TYPE_PADDING)
499 return die_("expected PADDING type");
501 return die_("expected is_last to be true");
502 /* check to see if some basic data matches (c.f. generate_file_()) */
503 if(block->length != 1234)
504 return die_("bad PADDING length");
506 if(FLAC__metadata_simple_iterator_next(iterator))
507 return die_("forward iterator returned true but should have returned false");
509 printf("iterate backwards\n");
510 if(!FLAC__metadata_simple_iterator_prev(iterator))
511 return die_("reverse iterator ended early");
512 if(!FLAC__metadata_simple_iterator_prev(iterator))
513 return die_("reverse iterator ended early");
514 if(FLAC__metadata_simple_iterator_prev(iterator))
515 return die_("reverse iterator returned true but should have returned false");
517 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
519 if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
520 printf("PASSED. FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
522 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
524 FLAC__metadata_simple_iterator_delete(iterator);
526 /************************************************************/
528 printf("simple iterator on writable file\n");
530 if(!change_stats_(flacfile_, /*read-only=*/false))
533 printf("creating APPLICATION block\n");
535 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
536 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
537 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
539 printf("creating PADDING block\n");
541 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
542 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
543 padding->length = 20;
545 if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
546 return die_("FLAC__metadata_simple_iterator_new()");
548 if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
549 return die_("FLAC__metadata_simple_iterator_init() returned false");
550 our_current_position = 0;
552 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
554 printf("[S]VP\ttry to write over STREAMINFO block...\n");
555 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
556 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
558 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
560 printf("[S]VP\tnext\n");
561 if(!FLAC__metadata_simple_iterator_next(iterator))
562 return die_("iterator ended early\n");
563 our_current_position++;
565 printf("S[V]P\tnext\n");
566 if(!FLAC__metadata_simple_iterator_next(iterator))
567 return die_("iterator ended early\n");
568 our_current_position++;
570 printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
571 padding->length = 25;
572 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
573 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
574 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
577 printf("SVP[P]\tprev\n");
578 if(!FLAC__metadata_simple_iterator_prev(iterator))
579 return die_("iterator ended early\n");
580 our_current_position--;
582 printf("SV[P]P\tprev\n");
583 if(!FLAC__metadata_simple_iterator_prev(iterator))
584 return die_("iterator ended early\n");
585 our_current_position--;
587 printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
588 padding->length = 30;
589 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
590 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
591 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
594 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
597 printf("SV[P]PP\tprev\n");
598 if(!FLAC__metadata_simple_iterator_prev(iterator))
599 return die_("iterator ended early\n");
600 our_current_position--;
602 printf("S[V]PPP\tprev\n");
603 if(!FLAC__metadata_simple_iterator_prev(iterator))
604 return die_("iterator ended early\n");
605 our_current_position--;
607 printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
608 if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
609 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
611 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
614 printf("[S]VPPP\tnext\n");
615 if(!FLAC__metadata_simple_iterator_next(iterator))
616 return die_("iterator ended early\n");
617 our_current_position++;
619 printf("S[V]PPP\tnext\n");
620 if(!FLAC__metadata_simple_iterator_next(iterator))
621 return die_("iterator ended early\n");
622 our_current_position++;
624 printf("SV[P]PP\tdelete (middle block), replace with padding\n");
625 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
626 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
627 our_current_position--;
629 printf("S[V]PPP\tnext\n");
630 if(!FLAC__metadata_simple_iterator_next(iterator))
631 return die_("iterator ended early\n");
632 our_current_position++;
634 printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
635 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
636 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
637 delete_from_our_metadata_(our_current_position--);
639 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
642 printf("S[V]PP\tnext\n");
643 if(!FLAC__metadata_simple_iterator_next(iterator))
644 return die_("iterator ended early\n");
645 our_current_position++;
647 printf("SV[P]P\tnext\n");
648 if(!FLAC__metadata_simple_iterator_next(iterator))
649 return die_("iterator ended early\n");
650 our_current_position++;
652 printf("SVP[P]\tdelete (last block), replace with padding\n");
653 if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
654 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
655 our_current_position--;
657 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
660 printf("SV[P]P\tnext\n");
661 if(!FLAC__metadata_simple_iterator_next(iterator))
662 return die_("iterator ended early\n");
663 our_current_position++;
665 printf("SVP[P]\tdelete (last block), don't replace with padding\n");
666 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
667 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
668 delete_from_our_metadata_(our_current_position--);
670 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
673 printf("SV[P]\tprev\n");
674 if(!FLAC__metadata_simple_iterator_prev(iterator))
675 return die_("iterator ended early\n");
676 our_current_position--;
678 printf("S[V]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]VP\tset STREAMINFO (change sample rate)\n");
684 FLAC__ASSERT(our_current_position == 0);
685 block = FLAC__metadata_simple_iterator_get_block(iterator);
686 block->data.stream_info.sample_rate = 32000;
687 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
688 return die_("copying object");
689 if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
690 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
691 FLAC__metadata_object_delete(block);
693 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
696 printf("[S]VP\tnext\n");
697 if(!FLAC__metadata_simple_iterator_next(iterator))
698 return die_("iterator ended early\n");
699 our_current_position++;
701 printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
702 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
703 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
704 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
705 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
707 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
709 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
712 printf("SV[A]P\tnext\n");
713 if(!FLAC__metadata_simple_iterator_next(iterator))
714 return die_("iterator ended early\n");
715 our_current_position++;
717 printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
718 app->data.application.id[0] = 'f'; /* twiddle the id */
719 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
720 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
721 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
723 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
725 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
728 printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
729 app->data.application.id[0] = 'g'; /* twiddle the id */
730 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
731 return die_("setting APPLICATION data");
732 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
733 return die_("copying object");
734 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
735 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
737 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
740 printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
741 app->data.application.id[0] = 'h'; /* twiddle the id */
742 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
743 return die_("setting APPLICATION data");
744 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
745 return die_("copying object");
746 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
747 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
749 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
752 printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
753 app->data.application.id[0] = 'i'; /* twiddle the id */
754 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
755 return die_("setting APPLICATION data");
756 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
757 return die_("copying object");
758 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
759 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
760 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
762 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
765 printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
766 app->data.application.id[0] = 'j'; /* twiddle the id */
767 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
768 return die_("setting APPLICATION data");
769 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
770 return die_("copying object");
771 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
772 return die_("copying object");
773 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
774 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
775 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
777 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
780 printf("SVA[A]PP\tnext\n");
781 if(!FLAC__metadata_simple_iterator_next(iterator))
782 return die_("iterator ended early\n");
783 our_current_position++;
785 printf("SVAA[P]P\tnext\n");
786 if(!FLAC__metadata_simple_iterator_next(iterator))
787 return die_("iterator ended early\n");
788 our_current_position++;
790 printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
792 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
793 return die_("copying object");
794 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
795 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
797 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
800 printf("SVAAP[P]\tset APPLICATION (grow)\n");
801 app->data.application.id[0] = 'k'; /* twiddle the id */
802 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
803 return die_("copying object");
804 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
805 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
807 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
810 printf("SVAAP[A]\tset PADDING (equal)\n");
811 padding->length = 27;
812 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
813 return die_("copying object");
814 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
815 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
817 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
820 printf("SVAAP[P]\tprev\n");
821 if(!FLAC__metadata_simple_iterator_prev(iterator))
822 return die_("iterator ended early\n");
823 our_current_position--;
825 printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
826 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
827 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
828 delete_from_our_metadata_(our_current_position--);
830 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
833 printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
834 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
835 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
836 delete_from_our_metadata_(our_current_position--);
838 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
841 printf("SV[A]P\tnext\n");
842 if(!FLAC__metadata_simple_iterator_next(iterator))
843 return die_("iterator ended early\n");
844 our_current_position++;
846 printf("SVA[P]\tinsert PADDING after\n");
848 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
849 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
850 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
853 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
856 printf("SVAP[P]\tprev\n");
857 if(!FLAC__metadata_simple_iterator_prev(iterator))
858 return die_("iterator ended early\n");
859 our_current_position--;
861 printf("SVA[P]P\tprev\n");
862 if(!FLAC__metadata_simple_iterator_prev(iterator))
863 return die_("iterator ended early\n");
864 our_current_position--;
866 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
867 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
868 return die_("setting APPLICATION data");
869 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
870 return die_("copying object");
871 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
872 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
874 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
877 printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
878 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
879 return die_("setting APPLICATION data");
880 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
881 return die_("copying object");
882 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
883 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
885 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
888 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
889 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
890 return die_("setting APPLICATION data");
891 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
892 return die_("copying object");
893 our_metadata_.blocks[our_current_position+1]->length = 0;
894 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
895 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
897 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
900 printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
901 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
902 return die_("setting APPLICATION data");
903 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
904 return die_("copying object");
905 delete_from_our_metadata_(our_current_position+1);
906 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
907 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
909 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
912 printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
913 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
914 return die_("setting APPLICATION data");
915 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
916 return die_("copying object");
917 delete_from_our_metadata_(our_current_position+1);
918 our_metadata_.blocks[our_current_position]->is_last = true;
919 if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
920 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
922 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
925 printf("SV[A]\tset PADDING (equal size)\n");
926 padding->length = app->length;
927 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
928 return die_("copying object");
929 if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
930 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
932 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
935 printf("SV[P]\tinsert PADDING after\n");
936 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
937 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
938 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
941 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
944 printf("SVP[P]\tinsert PADDING after\n");
946 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
947 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
948 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
951 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
954 printf("SVPP[P]\tprev\n");
955 if(!FLAC__metadata_simple_iterator_prev(iterator))
956 return die_("iterator ended early\n");
957 our_current_position--;
959 printf("SVP[P]P\tprev\n");
960 if(!FLAC__metadata_simple_iterator_prev(iterator))
961 return die_("iterator ended early\n");
962 our_current_position--;
964 printf("SV[P]PP\tprev\n");
965 if(!FLAC__metadata_simple_iterator_prev(iterator))
966 return die_("iterator ended early\n");
967 our_current_position--;
969 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
970 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
971 return die_("setting APPLICATION data");
972 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
973 return die_("copying object");
974 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
975 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
977 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
980 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
981 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
982 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
983 delete_from_our_metadata_(our_current_position--);
985 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
988 printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
989 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
990 return die_("setting APPLICATION data");
991 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
992 return die_("copying object");
993 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
994 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
996 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
999 printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1000 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1001 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1002 delete_from_our_metadata_(our_current_position--);
1004 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1007 printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1008 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1009 return die_("setting APPLICATION data");
1010 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1011 return die_("copying object");
1012 delete_from_our_metadata_(our_current_position+1);
1013 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1014 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1016 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1019 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1020 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1021 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1022 delete_from_our_metadata_(our_current_position--);
1024 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1027 printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1028 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1029 return die_("setting APPLICATION data");
1030 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1031 return die_("copying object");
1032 our_metadata_.blocks[our_current_position+1]->length = 0;
1033 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1034 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1036 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1039 printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1040 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1041 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1042 delete_from_our_metadata_(our_current_position--);
1044 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1047 printf("S[V]PP\tnext\n");
1048 if(!FLAC__metadata_simple_iterator_next(iterator))
1049 return die_("iterator ended early\n");
1050 our_current_position++;
1052 printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1053 if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1054 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1055 delete_from_our_metadata_(our_current_position--);
1057 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1060 printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1061 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1062 return die_("setting APPLICATION data");
1063 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1064 return die_("copying object");
1065 delete_from_our_metadata_(our_current_position+1);
1066 if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1067 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1069 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1072 printf("delete simple iterator\n");
1074 FLAC__metadata_simple_iterator_delete(iterator);
1076 FLAC__metadata_object_delete(app);
1077 FLAC__metadata_object_delete(padding);
1079 if(!remove_file_(flacfile_))
1085 static FLAC__bool test_level_2_()
1087 FLAC__Metadata_Iterator *iterator;
1088 FLAC__Metadata_Chain *chain;
1089 FLAC__StreamMetadata *block, *app, *padding;
1090 FLAC__byte data[2000];
1091 unsigned our_current_position;
1093 printf("\n\n++++++ testing level 2 interface\n");
1095 printf("generate read-only file\n");
1097 if(!generate_file_())
1100 if(!change_stats_(flacfile_, /*read_only=*/true))
1103 printf("create chain\n");
1105 if(0 == (chain = FLAC__metadata_chain_new()))
1106 return die_("allocating chain");
1108 printf("read chain\n");
1110 if(!FLAC__metadata_chain_read(chain, flacfile_))
1111 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1113 printf("[S]VP\ttest initial metadata\n");
1115 if(!compare_chain_(chain, 0, 0))
1117 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1120 printf("switch file to read-write\n");
1122 if(!change_stats_(flacfile_, /*read-only=*/false))
1125 printf("create iterator\n");
1126 if(0 == (iterator = FLAC__metadata_iterator_new()))
1127 return die_("allocating memory for iterator");
1129 our_current_position = 0;
1131 FLAC__metadata_iterator_init(iterator, chain);
1133 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1134 return die_("getting block from iterator");
1136 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1138 printf("[S]VP\tmodify STREAMINFO, write\n");
1140 block->data.stream_info.sample_rate = 32000;
1141 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1142 return die_("copying object");
1144 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/true))
1145 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1146 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1148 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1151 printf("[S]VP\tnext\n");
1152 if(!FLAC__metadata_iterator_next(iterator))
1153 return die_("iterator ended early\n");
1154 our_current_position++;
1156 printf("S[V]P\tnext\n");
1157 if(!FLAC__metadata_iterator_next(iterator))
1158 return die_("iterator ended early\n");
1159 our_current_position++;
1161 printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1162 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1163 return die_("getting block from iterator");
1164 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1165 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1166 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1167 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1168 return die_("setting APPLICATION data");
1169 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1170 return die_("copying object");
1171 if(!FLAC__metadata_iterator_set_block(iterator, app))
1172 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1174 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1175 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1176 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1178 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1181 printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1182 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1183 return die_("copying object");
1184 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1185 return die_("setting APPLICATION data");
1186 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1187 return die_("copying object");
1188 if(!FLAC__metadata_iterator_set_block(iterator, app))
1189 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1191 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1192 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1193 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1195 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1198 printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1199 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1200 return die_("copying object");
1201 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1202 return die_("setting APPLICATION data");
1203 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1204 return die_("copying object");
1205 if(!FLAC__metadata_iterator_set_block(iterator, app))
1206 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1208 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1209 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1210 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1212 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1215 printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1216 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1217 return die_("copying object");
1218 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1219 return die_("setting APPLICATION data");
1220 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1221 return die_("copying object");
1222 if(!FLAC__metadata_iterator_set_block(iterator, app))
1223 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1225 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1226 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1227 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1229 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1232 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1233 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1234 return die_("copying object");
1235 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1236 return die_("setting APPLICATION data");
1237 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1238 return die_("copying object");
1239 if(!FLAC__metadata_iterator_set_block(iterator, app))
1240 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1242 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1243 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1244 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1246 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1249 printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1250 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1251 return die_("creating PADDING block");
1252 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1253 return die_("copying object");
1254 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1255 return die_("setting APPLICATION data");
1256 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1257 return die_("copying object");
1258 padding->length = 0;
1259 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1260 return die_("internal error");
1261 if(!FLAC__metadata_iterator_set_block(iterator, app))
1262 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1264 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1265 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1266 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1268 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1271 printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1272 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1273 return die_("copying object");
1274 if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1275 return die_("setting APPLICATION data");
1276 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1277 return die_("copying object");
1278 our_metadata_.blocks[our_current_position+1]->length = 13;
1279 if(!FLAC__metadata_iterator_set_block(iterator, app))
1280 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1282 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1283 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1284 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1286 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1289 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1290 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1291 return die_("copying object");
1292 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1293 return die_("setting APPLICATION data");
1294 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1295 return die_("copying object");
1296 if(!FLAC__metadata_iterator_set_block(iterator, app))
1297 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1299 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1300 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1301 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1303 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1306 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1307 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1308 return die_("copying object");
1309 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1310 return die_("setting APPLICATION data");
1311 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1312 return die_("copying object");
1313 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1314 if(!FLAC__metadata_iterator_set_block(iterator, app))
1315 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1317 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1318 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1319 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1321 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1324 printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1325 if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1326 return die_("copying object");
1327 if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1328 return die_("setting APPLICATION data");
1329 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1330 return die_("copying object");
1331 delete_from_our_metadata_(our_current_position+1);
1332 if(!FLAC__metadata_iterator_set_block(iterator, app))
1333 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1335 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1336 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1337 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1339 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1342 printf("SV[A]\tprev\n");
1343 if(!FLAC__metadata_iterator_prev(iterator))
1344 return die_("iterator ended early\n");
1345 our_current_position--;
1347 printf("S[V]A\tprev\n");
1348 if(!FLAC__metadata_iterator_prev(iterator))
1349 return die_("iterator ended early\n");
1350 our_current_position--;
1352 printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1353 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1354 return die_("creating PADDING block");
1355 padding->length = 30;
1356 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1357 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1359 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1361 printf("[S]VP\tnext\n");
1362 if(!FLAC__metadata_iterator_next(iterator))
1363 return die_("iterator ended early\n");
1364 our_current_position++;
1366 printf("S[V]A\tinsert PADDING after\n");
1367 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1368 return die_("copying metadata");
1369 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1370 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1372 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1375 printf("SV[P]A\tinsert PADDING before\n");
1376 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1377 return die_("creating PADDING block");
1378 padding->length = 17;
1379 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1380 return die_("copying metadata");
1381 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1382 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1384 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1387 printf("SV[P]PA\tinsert PADDING before\n");
1388 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1389 return die_("creating PADDING block");
1390 padding->length = 0;
1391 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1392 return die_("copying metadata");
1393 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1394 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1396 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1399 printf("SV[P]PPA\tnext\n");
1400 if(!FLAC__metadata_iterator_next(iterator))
1401 return die_("iterator ended early\n");
1402 our_current_position++;
1404 printf("SVP[P]PA\tnext\n");
1405 if(!FLAC__metadata_iterator_next(iterator))
1406 return die_("iterator ended early\n");
1407 our_current_position++;
1409 printf("SVPP[P]A\tnext\n");
1410 if(!FLAC__metadata_iterator_next(iterator))
1411 return die_("iterator ended early\n");
1412 our_current_position++;
1414 printf("SVPPP[A]\tinsert PADDING after\n");
1415 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1416 return die_("creating PADDING block");
1417 padding->length = 57;
1418 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1419 return die_("copying metadata");
1420 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1421 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1423 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1426 printf("SVPPPA[P]\tinsert PADDING before\n");
1427 if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1428 return die_("creating PADDING block");
1429 padding->length = 99;
1430 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1431 return die_("copying metadata");
1432 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1433 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1435 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1438 printf("delete iterator\n");
1439 FLAC__metadata_iterator_delete(iterator);
1440 our_current_position = 0;
1442 printf("SVPPPAPP\tmerge padding\n");
1443 FLAC__metadata_chain_merge_padding(chain);
1444 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1445 our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1446 our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1447 delete_from_our_metadata_(7);
1448 delete_from_our_metadata_(4);
1449 delete_from_our_metadata_(3);
1451 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1452 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1453 if(!compare_chain_(chain, 0, 0))
1455 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1458 printf("SVPAP\tsort padding\n");
1459 FLAC__metadata_chain_sort_padding(chain);
1460 our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1461 delete_from_our_metadata_(2);
1463 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1464 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1465 if(!compare_chain_(chain, 0, 0))
1467 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1470 printf("create iterator\n");
1471 if(0 == (iterator = FLAC__metadata_iterator_new()))
1472 return die_("allocating memory for iterator");
1474 our_current_position = 0;
1476 FLAC__metadata_iterator_init(iterator, chain);
1478 printf("[S]VAP\tnext\n");
1479 if(!FLAC__metadata_iterator_next(iterator))
1480 return die_("iterator ended early\n");
1481 our_current_position++;
1483 printf("S[V]AP\tnext\n");
1484 if(!FLAC__metadata_iterator_next(iterator))
1485 return die_("iterator ended early\n");
1486 our_current_position++;
1488 printf("SV[A]P\tdelete middle block, replace with padding\n");
1489 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1490 return die_("creating PADDING block");
1491 padding->length = 71;
1492 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1493 return die_("copying object");
1494 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1495 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1497 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1500 printf("S[V]PP\tnext\n");
1501 if(!FLAC__metadata_iterator_next(iterator))
1502 return die_("iterator ended early\n");
1503 our_current_position++;
1505 printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1506 delete_from_our_metadata_(our_current_position--);
1507 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1508 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1510 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1513 printf("S[V]P\tnext\n");
1514 if(!FLAC__metadata_iterator_next(iterator))
1515 return die_("iterator ended early\n");
1516 our_current_position++;
1518 printf("SV[P]\tdelete last block, replace with padding\n");
1519 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1520 return die_("creating PADDING block");
1521 padding->length = 219;
1522 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1523 return die_("copying object");
1524 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1525 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1527 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1530 printf("S[V]P\tnext\n");
1531 if(!FLAC__metadata_iterator_next(iterator))
1532 return die_("iterator ended early\n");
1533 our_current_position++;
1535 printf("SV[P]\tdelete last block, don't replace with padding\n");
1536 delete_from_our_metadata_(our_current_position--);
1537 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1538 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1540 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1543 printf("S[V]\tprev\n");
1544 if(!FLAC__metadata_iterator_prev(iterator))
1545 return die_("iterator ended early\n");
1546 our_current_position--;
1548 printf("[S]V\tdelete STREAMINFO block, should fail\n");
1549 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1550 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1552 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1555 printf("delete iterator\n");
1556 FLAC__metadata_iterator_delete(iterator);
1557 our_current_position = 0;
1559 printf("SV\tmerge padding\n");
1560 FLAC__metadata_chain_merge_padding(chain);
1562 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1563 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1564 if(!compare_chain_(chain, 0, 0))
1566 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1569 printf("SV\tsort padding\n");
1570 FLAC__metadata_chain_sort_padding(chain);
1572 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1573 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1574 if(!compare_chain_(chain, 0, 0))
1576 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1579 printf("delete chain\n");
1581 FLAC__metadata_chain_delete(chain);
1583 if(!remove_file_(flacfile_))
1589 FLAC__bool test_metadata_file_manipulation()
1591 printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1593 our_metadata_.num_blocks = 0;
1595 if(!test_level_0_())
1598 if(!test_level_1_())
1601 if(!test_level_2_())