1 /* test_libFLAC - Unit tester for libFLAC
2 * Copyright (C) 2002 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include "file_utils.h"
20 #include "metadata_utils.h"
21 #include "FLAC/assert.h"
22 #include "FLAC/file_decoder.h"
23 #include "FLAC/metadata.h"
25 #include <stdlib.h> /* for malloc() */
27 /******************************************************************************
28 The general strategy of these tests (for interface levels 1 and 2) is
29 to create a dummy FLAC file with a known set of initial metadata
30 blocks, then keep a mirror locally of what we expect the metadata to be
31 after each operation. Then testing becomes a simple matter of running
32 a FLAC__FileDecoder over the dummy file after each operation, comparing
33 the decoded metadata to what's in our local copy. If there are any
34 differences in the metadata, or the actual audio data is corrupted, we
35 will catch it while decoding.
36 ******************************************************************************/
39 FLAC__bool error_occurred;
40 } decoder_client_struct;
43 FLAC__StreamMetaData *blocks[64];
45 } our_metadata_struct;
47 static const char *flacfile_ = "metadata.flac";
49 /* our copy of the metadata in flacfile_ */
50 static our_metadata_struct our_metadata_;
52 /* the current block number that corresponds to the position of the iterator we are testing */
53 static unsigned mc_our_block_number_ = 0;
55 static FLAC__bool die_(const char *msg)
57 printf("ERROR: %s\n", msg);
61 static FLAC__bool die_c_(const char *msg, FLAC__MetaData_ChainStatus status)
63 printf("ERROR: %s\n", msg);
64 printf(" status=%s\n", FLAC__MetaData_ChainStatusString[status]);
68 static FLAC__bool die_ss_(const char *msg, FLAC__MetaData_SimpleIterator *siterator)
70 printf("ERROR: %s\n", msg);
71 printf(" status=%s\n", FLAC__MetaData_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(siterator)]);
75 /* functions for working with our metadata copy */
77 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetaData *block, unsigned position, FLAC__bool copy)
80 FLAC__StreamMetaData *obj = block;
81 FLAC__ASSERT(position < our_metadata_.num_blocks);
83 if(0 == (obj = FLAC__metadata_object_copy(block)))
84 return die_("during FLAC__metadata_object_copy()");
86 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
87 our_metadata_.blocks[position] = obj;
89 /* set the is_last flags */
90 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
91 our_metadata_.blocks[i]->is_last = false;
92 our_metadata_.blocks[i]->is_last = true;
97 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetaData *block, unsigned position, FLAC__bool copy)
100 FLAC__StreamMetaData *obj = block;
102 if(0 == (obj = FLAC__metadata_object_copy(block)))
103 return die_("during FLAC__metadata_object_copy()");
105 if(position > our_metadata_.num_blocks) {
106 position = our_metadata_.num_blocks;
109 for(i = our_metadata_.num_blocks; i > position; i--)
110 our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
112 our_metadata_.blocks[position] = obj;
113 our_metadata_.num_blocks++;
115 /* set the is_last flags */
116 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
117 our_metadata_.blocks[i]->is_last = false;
118 our_metadata_.blocks[i]->is_last = true;
123 static void delete_from_our_metadata_(unsigned position)
126 FLAC__ASSERT(position < our_metadata_.num_blocks);
127 FLAC__metadata_object_delete(our_metadata_.blocks[position]);
128 for(i = position; i < our_metadata_.num_blocks - 1; i++)
129 our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
130 our_metadata_.num_blocks--;
132 /* set the is_last flags */
133 if(our_metadata_.num_blocks > 0) {
134 for(i = 0; i < our_metadata_.num_blocks - 1; i++)
135 our_metadata_.blocks[i]->is_last = false;
136 our_metadata_.blocks[i]->is_last = true;
140 /* function for comparing our metadata to a FLAC__MetaData_Chain */
142 static FLAC__bool compare_chain_(FLAC__MetaData_Chain *chain, unsigned current_position, FLAC__StreamMetaData *current_block)
145 FLAC__MetaData_Iterator *iterator;
146 FLAC__StreamMetaData *block;
147 FLAC__bool next_ok = true;
149 FLAC__ASSERT(0 != chain);
151 printf("\tcomparing chain... ");
154 if(0 == (iterator = FLAC__metadata_iterator_new()))
155 return die_("allocating memory for iterator");
157 FLAC__metadata_iterator_init(iterator, chain);
164 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
165 FLAC__metadata_iterator_delete(iterator);
166 return die_("getting block from iterator");
169 if(!compare_block_(our_metadata_.blocks[i], block)) {
170 FLAC__metadata_iterator_delete(iterator);
171 return die_("metadata block mismatch");
175 next_ok = FLAC__metadata_iterator_next(iterator);
176 } while(i < our_metadata_.num_blocks && next_ok);
178 FLAC__metadata_iterator_delete(iterator);
181 return die_("chain has more blocks than expected");
183 if(i < our_metadata_.num_blocks)
184 return die_("short block count in chain");
186 if(0 != current_block) {
187 printf("CURRENT_POSITION... ");
190 if(!compare_block_(our_metadata_.blocks[current_position], current_block))
191 return die_("metadata block mismatch");
199 /* decoder callbacks for checking the file */
201 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
203 (void)decoder, (void)buffer, (void)client_data;
206 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
207 (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
209 printf("content... ");
213 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
216 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
218 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
221 dcd->error_occurred = true;
222 printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
225 /* this version pays no attention to the metadata */
226 static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
228 (void)decoder, (void)metadata, (void)client_data;
230 printf("%d... ", mc_our_block_number_);
233 mc_our_block_number_++;
236 /* this version is used when we want to compare to our metadata copy */
237 static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
239 decoder_client_struct *dcd = (decoder_client_struct*)client_data;
243 /* don't bother checking if we've already hit an error */
244 if(dcd->error_occurred)
247 printf("%d... ", mc_our_block_number_);
250 if(mc_our_block_number_ >= our_metadata_.num_blocks) {
251 (void)die_("got more metadata blocks than expected");
252 dcd->error_occurred = true;
255 if(!compare_block_(our_metadata_.blocks[mc_our_block_number_], metadata)) {
256 (void)die_("metadata block mismatch");
257 dcd->error_occurred = true;
260 mc_our_block_number_++;
263 static FLAC__bool generate_file_()
265 FLAC__StreamMetaData streaminfo, padding;
266 FLAC__StreamMetaData *metadata[1];
268 printf("generating FLAC file for test\n");
270 while(our_metadata_.num_blocks > 0)
271 delete_from_our_metadata_(0);
273 streaminfo.is_last = false;
274 streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
275 streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
276 streaminfo.data.stream_info.min_blocksize = 576;
277 streaminfo.data.stream_info.max_blocksize = 576;
278 streaminfo.data.stream_info.min_framesize = 0;
279 streaminfo.data.stream_info.max_framesize = 0;
280 streaminfo.data.stream_info.sample_rate = 44100;
281 streaminfo.data.stream_info.channels = 1;
282 streaminfo.data.stream_info.bits_per_sample = 8;
283 streaminfo.data.stream_info.total_samples = 0;
284 memset(streaminfo.data.stream_info.md5sum, 0, 16);
286 padding.is_last = true;
287 padding.type = FLAC__METADATA_TYPE_PADDING;
288 padding.length = 1234;
290 metadata[0] = &padding;
292 if(!insert_to_our_metadata_(&streaminfo, 0, /*copy=*/true) || !insert_to_our_metadata_(&padding, 1, /*copy=*/true))
293 return die_("priming our metadata");
295 if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
296 return die_("creating the encoded file");
301 static FLAC__bool test_file_(const char *filename, void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data))
303 FLAC__FileDecoder *decoder;
304 decoder_client_struct decoder_client_data;
306 FLAC__ASSERT(0 != filename);
307 FLAC__ASSERT(0 != metadata_callback);
309 mc_our_block_number_ = 0;
310 decoder_client_data.error_occurred = false;
312 printf("\ttesting '%s'... ", filename);
315 if(0 == (decoder = FLAC__file_decoder_new()))
316 return die_("couldn't allocate memory");
318 FLAC__file_decoder_set_md5_checking(decoder, true);
319 FLAC__file_decoder_set_filename(decoder, filename);
320 FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
321 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
322 FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
323 FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
324 FLAC__file_decoder_set_metadata_respond_all(decoder);
325 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
326 FLAC__file_decoder_finish(decoder);
327 FLAC__file_decoder_delete(decoder);
328 return die_("initializing decoder\n");
330 if(!FLAC__file_decoder_process_whole_file(decoder)) {
331 FLAC__file_decoder_finish(decoder);
332 FLAC__file_decoder_delete(decoder);
333 return die_("decoding file\n");
336 FLAC__file_decoder_finish(decoder);
337 FLAC__file_decoder_delete(decoder);
339 if(decoder_client_data.error_occurred)
342 if(mc_our_block_number_ != our_metadata_.num_blocks)
343 return die_("short metadata block count");
349 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
351 if(!file_utils__change_stats(filename, read_only))
352 return die_("during file_utils__change_stats()");
357 static FLAC__bool remove_file_(const char *filename)
359 while(our_metadata_.num_blocks > 0)
360 delete_from_our_metadata_(0);
362 if(!file_utils__remove_file(filename))
363 return die_("removing file");
368 static FLAC__bool test_level_0_()
370 FLAC__StreamMetaData_StreamInfo streaminfo;
372 printf("\n\n++++++ testing level 0 interface\n");
374 if(!generate_file_())
377 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
380 if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
381 return die_("during FLAC__metadata_get_streaminfo()");
383 /* check to see if some basic data matches (c.f. generate_file_()) */
384 if(streaminfo.channels != 1)
385 return die_("mismatch in streaminfo.channels");
386 if(streaminfo.bits_per_sample != 8)
387 return die_("mismatch in streaminfo.bits_per_sample");
388 if(streaminfo.sample_rate != 44100)
389 return die_("mismatch in streaminfo.sample_rate");
390 if(streaminfo.min_blocksize != 576)
391 return die_("mismatch in streaminfo.min_blocksize");
392 if(streaminfo.max_blocksize != 576)
393 return die_("mismatch in streaminfo.max_blocksize");
395 if(!remove_file_(flacfile_))
401 static FLAC__bool test_level_1_()
403 FLAC__MetaData_SimpleIterator *siterator;
404 FLAC__StreamMetaData *block, *app, *padding;
405 FLAC__byte data[1000];
406 unsigned our_current_position = 0;
408 printf("\n\n++++++ testing level 1 interface\n");
410 /************************************************************/
412 printf("simple iterator on read-only file\n");
414 if(!generate_file_())
417 if(!change_stats_(flacfile_, /*read_only=*/true))
420 if(!test_file_(flacfile_, decoder_metadata_callback_null_))
423 if(0 == (siterator = FLAC__metadata_simple_iterator_new()))
424 return die_("FLAC__metadata_simple_iterator_new()");
426 if(!FLAC__metadata_simple_iterator_init(siterator, flacfile_, false))
427 return die_("ERROR: FLAC__metadata_simple_iterator_init()\n");
429 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(siterator));
430 if(FLAC__metadata_simple_iterator_is_writable(siterator))
431 return die_("iterator claims file is writable when it should not be\n");
433 printf("iterate forwards\n");
435 if(FLAC__metadata_simple_iterator_get_block_type(siterator) != FLAC__METADATA_TYPE_STREAMINFO)
436 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
437 if(0 == (block = FLAC__metadata_simple_iterator_get_block(siterator)))
438 return die_("getting block 0");
439 if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
440 return die_("expected STREAMINFO type");
442 return die_("expected is_last to be false");
443 if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
444 return die_("bad STREAMINFO length");
445 /* check to see if some basic data matches (c.f. generate_file_()) */
446 if(block->data.stream_info.channels != 1)
447 return die_("mismatch in channels");
448 if(block->data.stream_info.bits_per_sample != 8)
449 return die_("mismatch in bits_per_sample");
450 if(block->data.stream_info.sample_rate != 44100)
451 return die_("mismatch in sample_rate");
452 if(block->data.stream_info.min_blocksize != 576)
453 return die_("mismatch in min_blocksize");
454 if(block->data.stream_info.max_blocksize != 576)
455 return die_("mismatch in max_blocksize");
457 if(!FLAC__metadata_simple_iterator_next(siterator))
458 return die_("forward iterator ended early");
459 our_current_position++;
461 if(FLAC__metadata_simple_iterator_get_block_type(siterator) != FLAC__METADATA_TYPE_PADDING)
462 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
463 if(0 == (block = FLAC__metadata_simple_iterator_get_block(siterator)))
464 return die_("getting block 1");
465 if(block->type != FLAC__METADATA_TYPE_PADDING)
466 return die_("expected PADDING type");
468 return die_("expected is_last to be true");
469 /* check to see if some basic data matches (c.f. generate_file_()) */
470 if(block->length != 1234)
471 return die_("bad STREAMINFO length");
473 if(FLAC__metadata_simple_iterator_next(siterator))
474 return die_("forward iterator returned true but should have returned false");
476 printf("iterate backwards\n");
477 if(!FLAC__metadata_simple_iterator_prev(siterator))
478 return die_("reverse iterator ended early");
479 if(FLAC__metadata_simple_iterator_prev(siterator))
480 return die_("reverse iterator returned true but should have returned false");
482 printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
484 if(!FLAC__metadata_simple_iterator_set_block(siterator, (FLAC__StreamMetaData*)99, false))
485 printf("PASSED. FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
487 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
489 FLAC__metadata_simple_iterator_delete(siterator);
491 /************************************************************/
493 printf("simple iterator on writable file\n");
495 if(!change_stats_(flacfile_, /*read-only=*/false))
498 printf("creating APPLICATION block\n");
500 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
501 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
502 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
504 printf("creating PADDING block\n");
506 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
507 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
508 padding->length = 20;
510 if(0 == (siterator = FLAC__metadata_simple_iterator_new()))
511 return die_("FLAC__metadata_simple_iterator_new()");
513 if(!FLAC__metadata_simple_iterator_init(siterator, flacfile_, /*preserve_file_stats=*/false))
514 return die_("ERROR: FLAC__metadata_simple_iterator_init()\n");
515 our_current_position = 0;
517 printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(siterator));
519 printf("[S]P\ttry to write over STREAMINFO block...\n");
520 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, false))
521 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
523 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
525 printf("[S]P\tnext\n");
526 if(!FLAC__metadata_simple_iterator_next(siterator))
527 return die_("iterator ended early\n");
528 our_current_position++;
530 printf("S[P]\tinsert PADDING after, don't expand into padding\n");
531 padding->length = 25;
532 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false))
533 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false)", siterator);
534 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
537 printf("SP[P]\tprev\n");
538 if(!FLAC__metadata_simple_iterator_prev(siterator))
539 return die_("iterator ended early\n");
540 our_current_position--;
542 printf("S[P]P\tprev\n");
543 if(!FLAC__metadata_simple_iterator_prev(siterator))
544 return die_("iterator ended early\n");
545 our_current_position--;
547 printf("[S]PP\tinsert PADDING after, don't expand into padding\n");
548 padding->length = 30;
549 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false))
550 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false)", siterator);
551 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
554 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
557 printf("S[P]PP\tprev\n");
558 if(!FLAC__metadata_simple_iterator_prev(siterator))
559 return die_("iterator ended early\n");
560 our_current_position--;
562 printf("[S]PPP\tdelete (STREAMINFO block), must fail\n");
563 if(FLAC__metadata_simple_iterator_delete_block(siterator, false))
564 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false) should have returned false", siterator);
566 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
569 printf("[S]PPP\tnext\n");
570 if(!FLAC__metadata_simple_iterator_next(siterator))
571 return die_("iterator ended early\n");
572 our_current_position++;
574 printf("S[P]PP\tdelete (middle block), replace with padding\n");
575 if(!FLAC__metadata_simple_iterator_delete_block(siterator, true))
576 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, true)", siterator);
577 our_current_position--;
579 printf("[S]PPP\tnext\n");
580 if(!FLAC__metadata_simple_iterator_next(siterator))
581 return die_("iterator ended early\n");
582 our_current_position++;
584 printf("S[P]PP\tdelete (middle block), don't replace with padding\n");
585 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
586 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
587 delete_from_our_metadata_(our_current_position--);
589 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
592 printf("[S]PP\tnext\n");
593 if(!FLAC__metadata_simple_iterator_next(siterator))
594 return die_("iterator ended early\n");
595 our_current_position++;
597 printf("S[P]P\tnext\n");
598 if(!FLAC__metadata_simple_iterator_next(siterator))
599 return die_("iterator ended early\n");
600 our_current_position++;
602 printf("SP[P]\tdelete (last block), replace with padding\n");
603 if(!FLAC__metadata_simple_iterator_delete_block(siterator, true))
604 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
605 our_current_position--;
607 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
610 printf("S[P]P\tnext\n");
611 if(!FLAC__metadata_simple_iterator_next(siterator))
612 return die_("iterator ended early\n");
613 our_current_position++;
615 printf("SP[P]\tdelete (last block), don't replace with padding\n");
616 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
617 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
618 delete_from_our_metadata_(our_current_position--);
620 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
623 printf("S[P]\tprev\n");
624 if(!FLAC__metadata_simple_iterator_prev(siterator))
625 return die_("iterator ended early\n");
626 our_current_position--;
628 printf("[S]P\tset STREAMINFO (change sample rate)\n");
629 FLAC__ASSERT(our_current_position == 0);
630 block = FLAC__metadata_simple_iterator_get_block(siterator);
631 block->data.stream_info.sample_rate = 32000;
632 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
633 return die_("copying object");
634 if(!FLAC__metadata_simple_iterator_set_block(siterator, block, false))
635 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, block, false)", siterator);
636 FLAC__metadata_object_delete(block);
638 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
641 printf("[S]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
642 app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
643 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true))
644 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true)", siterator);
645 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
647 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
649 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
652 printf("S[A]P\tnext\n");
653 if(!FLAC__metadata_simple_iterator_next(siterator))
654 return die_("iterator ended early\n");
655 our_current_position++;
657 printf("SA[P]\tset APPLICATION, expand into padding of exceeding size\n");
658 app->data.application.id[0] = 'f'; /* twiddle the id */
659 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
660 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
661 if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
663 our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
665 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
668 printf("SA[A]P\tset APPLICATION (grow), don't expand into padding\n");
669 app->data.application.id[0] = 'g'; /* twiddle the id */
670 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
671 return die_("setting APPLICATION data");
672 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
673 return die_("copying object");
674 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, false))
675 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, false)", siterator);
677 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
680 printf("SA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
681 app->data.application.id[0] = 'h'; /* twiddle the id */
682 if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
683 return die_("setting APPLICATION data");
684 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
685 return die_("copying object");
686 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, false))
687 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, false)", siterator);
689 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
692 printf("SA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
693 app->data.application.id[0] = 'i'; /* twiddle the id */
694 if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
695 return die_("setting APPLICATION data");
696 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
697 return die_("copying object");
698 our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
699 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
700 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
702 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
705 printf("SA[A]P\tset APPLICATION (shrink), fill in with padding\n");
706 app->data.application.id[0] = 'j'; /* twiddle the id */
707 if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
708 return die_("setting APPLICATION data");
709 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
710 return die_("copying object");
711 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
712 return die_("copying object");
713 our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
714 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
715 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
717 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
720 printf("SA[A]PP\tnext\n");
721 if(!FLAC__metadata_simple_iterator_next(siterator))
722 return die_("iterator ended early\n");
723 our_current_position++;
725 printf("SAA[P]P\tnext\n");
726 if(!FLAC__metadata_simple_iterator_next(siterator))
727 return die_("iterator ended early\n");
728 our_current_position++;
730 printf("SAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
732 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
733 return die_("copying object");
734 if(!FLAC__metadata_simple_iterator_set_block(siterator, padding, false))
735 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, padding, false)", siterator);
737 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
740 printf("SAAP[P]\tset APPLICATION (grow)\n");
741 app->data.application.id[0] = 'k'; /* twiddle the id */
742 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
743 return die_("copying object");
744 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, false))
745 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, false)", siterator);
747 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
750 printf("SAAP[A]\tset PADDING (equal)\n");
751 padding->length = 27;
752 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
753 return die_("copying object");
754 if(!FLAC__metadata_simple_iterator_set_block(siterator, padding, false))
755 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, padding, false)", siterator);
757 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
760 printf("SAAP[P]\tprev\n");
761 if(!FLAC__metadata_simple_iterator_prev(siterator))
762 return die_("iterator ended early\n");
763 our_current_position--;
765 printf("SAA[P]P\tdelete (middle block), don't replace with padding\n");
766 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
767 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
768 delete_from_our_metadata_(our_current_position--);
770 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
773 printf("SA[A]P\tdelete (middle block), don't replace with padding\n");
774 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
775 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
776 delete_from_our_metadata_(our_current_position--);
778 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
781 printf("S[A]P\tnext\n");
782 if(!FLAC__metadata_simple_iterator_next(siterator))
783 return die_("iterator ended early\n");
784 our_current_position++;
786 printf("SA[P]\tinsert PADDING after\n");
788 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false))
789 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false)", siterator);
790 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
793 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
796 printf("SAP[P]\tprev\n");
797 if(!FLAC__metadata_simple_iterator_prev(siterator))
798 return die_("iterator ended early\n");
799 our_current_position--;
801 printf("SA[P]P\tprev\n");
802 if(!FLAC__metadata_simple_iterator_prev(siterator))
803 return die_("iterator ended early\n");
804 our_current_position--;
806 printf("S[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
807 if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
808 return die_("setting APPLICATION data");
809 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
810 return die_("copying object");
811 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
812 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
814 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
817 printf("S[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
818 if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
819 return die_("setting APPLICATION data");
820 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
821 return die_("copying object");
822 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
823 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
825 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
828 printf("S[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
829 if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
830 return die_("setting APPLICATION data");
831 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
832 return die_("copying object");
833 our_metadata_.blocks[our_current_position+1]->length = 0;
834 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
835 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
837 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
840 printf("S[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
841 if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
842 return die_("setting APPLICATION data");
843 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
844 return die_("copying object");
845 delete_from_our_metadata_(our_current_position+1);
846 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
847 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
849 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
852 printf("S[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
853 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
854 return die_("setting APPLICATION data");
855 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
856 return die_("copying object");
857 delete_from_our_metadata_(our_current_position+1);
858 our_metadata_.blocks[our_current_position]->is_last = true;
859 if(!FLAC__metadata_simple_iterator_set_block(siterator, app, true))
860 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, app, true)", siterator);
862 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
865 printf("S[A]\tset PADDING (equal size)\n");
866 padding->length = app->length;
867 if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
868 return die_("copying object");
869 if(!FLAC__metadata_simple_iterator_set_block(siterator, padding, true))
870 return die_ss_("FLAC__metadata_simple_iterator_set_block(siterator, padding, true)", siterator);
872 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
875 printf("S[P]\tinsert PADDING after\n");
876 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false))
877 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false)", siterator);
878 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
881 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
884 printf("SP[P]\tinsert PADDING after\n");
886 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false))
887 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, padding, false)", siterator);
888 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
891 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
894 printf("SPP[P]\tprev\n");
895 if(!FLAC__metadata_simple_iterator_prev(siterator))
896 return die_("iterator ended early\n");
897 our_current_position--;
899 printf("SP[P]P\tprev\n");
900 if(!FLAC__metadata_simple_iterator_prev(siterator))
901 return die_("iterator ended early\n");
902 our_current_position--;
904 printf("S[P]PP\tprev\n");
905 if(!FLAC__metadata_simple_iterator_prev(siterator))
906 return die_("iterator ended early\n");
907 our_current_position--;
909 printf("[S]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
910 if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
911 return die_("setting APPLICATION data");
912 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
913 return die_("copying object");
914 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true))
915 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true)", siterator);
917 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
920 printf("S[A]PPP\tdelete (middle block), don't replace with padding\n");
921 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
922 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
923 delete_from_our_metadata_(our_current_position--);
925 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
928 printf("[S]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
929 if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
930 return die_("setting APPLICATION data");
931 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
932 return die_("copying object");
933 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true))
934 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true)", siterator);
936 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
939 printf("S[A]PPP\tdelete (middle block), don't replace with padding\n");
940 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
941 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
942 delete_from_our_metadata_(our_current_position--);
944 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
947 printf("[S]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
948 if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
949 return die_("setting APPLICATION data");
950 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
951 return die_("copying object");
952 delete_from_our_metadata_(our_current_position+1);
953 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true))
954 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true)", siterator);
956 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
959 printf("S[A]PP\tdelete (middle block), don't replace with padding\n");
960 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
961 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
962 delete_from_our_metadata_(our_current_position--);
964 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
967 printf("[S]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
968 if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
969 return die_("setting APPLICATION data");
970 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
971 return die_("copying object");
972 our_metadata_.blocks[our_current_position+1]->length = 0;
973 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true))
974 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true)", siterator);
976 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
979 printf("S[A]PP\tdelete (middle block), don't replace with padding\n");
980 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
981 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
982 delete_from_our_metadata_(our_current_position--);
984 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
987 printf("[S]PP\tnext\n");
988 if(!FLAC__metadata_simple_iterator_next(siterator))
989 return die_("iterator ended early\n");
990 our_current_position++;
992 printf("S[P]P\tdelete (middle block), don't replace with padding\n");
993 if(!FLAC__metadata_simple_iterator_delete_block(siterator, false))
994 return die_ss_("FLAC__metadata_simple_iterator_delete_block(siterator, false)", siterator);
995 delete_from_our_metadata_(our_current_position--);
997 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1000 printf("[S]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1001 if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1002 return die_("setting APPLICATION data");
1003 if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1004 return die_("copying object");
1005 delete_from_our_metadata_(our_current_position+1);
1006 if(!FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true))
1007 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(siterator, app, true)", siterator);
1009 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1012 printf("delete simple iterator\n");
1014 FLAC__metadata_simple_iterator_delete(siterator);
1016 FLAC__metadata_object_delete(app);
1017 FLAC__metadata_object_delete(padding);
1019 if(!remove_file_(flacfile_))
1025 static FLAC__bool test_level_2_()
1027 FLAC__MetaData_Iterator *iterator;
1028 FLAC__MetaData_Chain *chain;
1029 FLAC__StreamMetaData *block, *app, *padding;
1030 FLAC__byte data[2000];
1031 unsigned our_current_position;
1033 printf("\n\n++++++ testing level 2 interface\n");
1035 printf("generate read-only file\n");
1037 if(!generate_file_())
1040 if(!change_stats_(flacfile_, /*read_only=*/true))
1043 printf("create chain\n");
1045 if(0 == (chain = FLAC__metadata_chain_new()))
1046 return die_("allocating chain");
1048 printf("read chain\n");
1050 if(!FLAC__metadata_chain_read(chain, flacfile_))
1051 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1053 printf("[S]P\ttest initial metadata\n");
1055 if(!compare_chain_(chain, 0, 0))
1057 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1060 printf("switch file to read-write\n");
1062 if(!change_stats_(flacfile_, /*read-only=*/false))
1065 printf("create iterator\n");
1066 if(0 == (iterator = FLAC__metadata_iterator_new()))
1067 return die_("allocating memory for iterator");
1069 our_current_position = 0;
1071 FLAC__metadata_iterator_init(iterator, chain);
1073 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1074 return die_("getting block from iterator");
1076 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1078 printf("[S]P\tmodify STREAMINFO, write\n");
1080 block->data.stream_info.sample_rate = 32000;
1081 if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1082 return die_("copying object");
1084 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/true))
1085 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1086 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1088 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1091 printf("[S]P\tnext\n");
1092 if(!FLAC__metadata_iterator_next(iterator))
1093 return die_("iterator ended early\n");
1094 our_current_position++;
1096 printf("S[P]\treplace PADDING with identical-size APPLICATION\n");
1097 if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1098 return die_("getting block from iterator");
1099 if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1100 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1101 memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1102 if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1103 return die_("setting APPLICATION data");
1104 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1105 return die_("copying object");
1106 if(!FLAC__metadata_iterator_set_block(iterator, app))
1107 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1109 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1110 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1111 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1113 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1116 printf("S[A]\tshrink APPLICATION, don't use padding\n");
1117 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1118 return die_("copying object");
1119 if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1120 return die_("setting APPLICATION data");
1121 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1122 return die_("copying object");
1123 if(!FLAC__metadata_iterator_set_block(iterator, app))
1124 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1126 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1127 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1128 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1130 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1133 printf("S[A]\tgrow APPLICATION, don't use padding\n");
1134 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1135 return die_("copying object");
1136 if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1137 return die_("setting APPLICATION data");
1138 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1139 return die_("copying object");
1140 if(!FLAC__metadata_iterator_set_block(iterator, app))
1141 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1143 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1144 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1145 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1147 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1150 printf("S[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1151 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1152 return die_("copying object");
1153 if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1154 return die_("setting APPLICATION data");
1155 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1156 return die_("copying object");
1157 if(!FLAC__metadata_iterator_set_block(iterator, app))
1158 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1160 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1161 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1162 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1164 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1167 printf("S[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1168 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1169 return die_("copying object");
1170 if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1171 return die_("setting APPLICATION data");
1172 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1173 return die_("copying object");
1174 if(!FLAC__metadata_iterator_set_block(iterator, app))
1175 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1177 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1178 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1179 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1181 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1184 printf("S[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1185 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1186 return die_("creating PADDING block");
1187 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1188 return die_("copying object");
1189 if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1190 return die_("setting APPLICATION data");
1191 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1192 return die_("copying object");
1193 padding->length = 0;
1194 if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1195 return die_("internal error");
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=*/true, /*preserve_file_stats=*/false))
1200 return die_c_("during FLAC__metadata_chain_write(chain, true, 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("S[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1207 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1208 return die_("copying object");
1209 if(!FLAC__metadata_object_application_set_data(app, data, 16, 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 our_metadata_.blocks[our_current_position+1]->length = 13;
1214 if(!FLAC__metadata_iterator_set_block(iterator, app))
1215 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1217 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1218 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1219 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1221 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1224 printf("S[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1225 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1226 return die_("copying object");
1227 if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1228 return die_("setting APPLICATION data");
1229 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1230 return die_("copying object");
1231 if(!FLAC__metadata_iterator_set_block(iterator, app))
1232 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1234 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1235 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1236 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1238 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1241 printf("S[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1242 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1243 return die_("copying object");
1244 if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1245 return die_("setting APPLICATION data");
1246 if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1247 return die_("copying object");
1248 our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1249 if(!FLAC__metadata_iterator_set_block(iterator, app))
1250 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1252 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1253 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1254 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1256 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1259 printf("S[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1260 if(0 == (app = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1261 return die_("copying object");
1262 if(!FLAC__metadata_object_application_set_data(app, data, 67, 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 delete_from_our_metadata_(our_current_position+1);
1267 if(!FLAC__metadata_iterator_set_block(iterator, app))
1268 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1270 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1271 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1272 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1274 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1277 printf("S[A]\tprev\n");
1278 if(!FLAC__metadata_iterator_prev(iterator))
1279 return die_("iterator ended early\n");
1280 our_current_position--;
1282 printf("[S]A\tinsert PADDING before STREAMINFO (should fail)\n");
1283 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1284 return die_("creating PADDING block");
1285 padding->length = 30;
1286 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1287 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1289 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1291 printf("[S]A\tinsert PADDING after\n");
1292 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1293 return die_("copying metadata");
1294 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1295 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1297 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1300 printf("S[P]A\tinsert PADDING before\n");
1301 if(0 == (padding = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1302 return die_("creating PADDING block");
1303 padding->length = 17;
1304 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1305 return die_("copying metadata");
1306 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1307 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1309 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1312 printf("S[P]PA\tinsert PADDING before\n");
1313 if(0 == (padding = FLAC__metadata_object_copy(our_metadata_.blocks[our_current_position])))
1314 return die_("creating PADDING block");
1315 padding->length = 0;
1316 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1317 return die_("copying metadata");
1318 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1319 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1321 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1324 printf("S[P]PPA\tnext\n");
1325 if(!FLAC__metadata_iterator_next(iterator))
1326 return die_("iterator ended early\n");
1327 our_current_position++;
1329 printf("SP[P]PA\tnext\n");
1330 if(!FLAC__metadata_iterator_next(iterator))
1331 return die_("iterator ended early\n");
1332 our_current_position++;
1334 printf("SPP[P]A\tnext\n");
1335 if(!FLAC__metadata_iterator_next(iterator))
1336 return die_("iterator ended early\n");
1337 our_current_position++;
1339 printf("SPPP[A]\tinsert PADDING after\n");
1340 if(0 == (padding = FLAC__metadata_object_copy(our_metadata_.blocks[1])))
1341 return die_("creating PADDING block");
1342 padding->length = 57;
1343 if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1344 return die_("copying metadata");
1345 if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1346 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1348 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1351 printf("SPPPA[P]\tinsert PADDING before\n");
1352 if(0 == (padding = FLAC__metadata_object_copy(our_metadata_.blocks[1])))
1353 return die_("creating PADDING block");
1354 padding->length = 99;
1355 if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1356 return die_("copying metadata");
1357 if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1358 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1360 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1363 printf("delete iterator\n");
1364 FLAC__metadata_iterator_delete(iterator);
1365 our_current_position = 0;
1367 printf("SPPPAPP\tmerge padding\n");
1368 FLAC__metadata_chain_merge_padding(chain);
1369 our_metadata_.blocks[1]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1370 our_metadata_.blocks[1]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1371 our_metadata_.blocks[5]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[6]->length);
1372 delete_from_our_metadata_(6);
1373 delete_from_our_metadata_(3);
1374 delete_from_our_metadata_(2);
1376 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1377 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1378 if(!compare_chain_(chain, 0, 0))
1380 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1383 printf("SPAP\tsort padding\n");
1384 FLAC__metadata_chain_sort_padding(chain);
1385 our_metadata_.blocks[3]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[1]->length);
1386 delete_from_our_metadata_(1);
1388 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1389 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1390 if(!compare_chain_(chain, 0, 0))
1392 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1395 printf("create iterator\n");
1396 if(0 == (iterator = FLAC__metadata_iterator_new()))
1397 return die_("allocating memory for iterator");
1399 our_current_position = 0;
1401 FLAC__metadata_iterator_init(iterator, chain);
1403 printf("[S]AP\tnext\n");
1404 if(!FLAC__metadata_iterator_next(iterator))
1405 return die_("iterator ended early\n");
1406 our_current_position++;
1408 printf("S[A]P\tdelete middle block, replace with padding\n");
1409 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1410 return die_("creating PADDING block");
1411 padding->length = 71;
1412 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1413 return die_("copying object");
1414 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1415 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1417 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1420 printf("[S]PP\tnext\n");
1421 if(!FLAC__metadata_iterator_next(iterator))
1422 return die_("iterator ended early\n");
1423 our_current_position++;
1425 printf("S[P]P\tdelete middle block, don't replace with padding\n");
1426 delete_from_our_metadata_(our_current_position--);
1427 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1428 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1430 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1433 printf("[S]P\tnext\n");
1434 if(!FLAC__metadata_iterator_next(iterator))
1435 return die_("iterator ended early\n");
1436 our_current_position++;
1438 printf("S[P]\tdelete last block, replace with padding\n");
1439 if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1440 return die_("creating PADDING block");
1441 padding->length = 219;
1442 if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1443 return die_("copying object");
1444 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1445 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1447 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1450 printf("[S]P\tnext\n");
1451 if(!FLAC__metadata_iterator_next(iterator))
1452 return die_("iterator ended early\n");
1453 our_current_position++;
1455 printf("S[P]\tdelete last block, don't replace with padding\n");
1456 delete_from_our_metadata_(our_current_position--);
1457 if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1458 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1460 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1463 printf("[S]\tdelete STREAMINFO block, should fail\n");
1464 if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1465 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1467 if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1470 printf("delete iterator\n");
1471 FLAC__metadata_iterator_delete(iterator);
1472 our_current_position = 0;
1474 printf("S\tmerge padding\n");
1475 FLAC__metadata_chain_merge_padding(chain);
1477 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1478 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1479 if(!compare_chain_(chain, 0, 0))
1481 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1484 printf("S\tsort padding\n");
1485 FLAC__metadata_chain_sort_padding(chain);
1487 if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1488 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1489 if(!compare_chain_(chain, 0, 0))
1491 if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1494 printf("delete chain\n");
1496 FLAC__metadata_chain_delete(chain);
1498 if(!remove_file_(flacfile_))
1504 FLAC__bool test_metadata_file_manipulation()
1506 printf("\n+++ unit test: metadata manipulation\n\n");
1508 our_metadata_.num_blocks = 0;
1510 if(!test_level_0_())
1513 if(!test_level_1_())
1516 if(!test_level_2_())