dee311c79ffe9f56c59423efcc45430aae55fd11
[platform/upstream/flac.git] / src / test_libFLAC / metadata_manip.c
1 /* test_libFLAC - Unit tester for libFLAC
2  * Copyright (C) 2002  Josh Coalson
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #include "file_utils.h"
20 #include "metadata_utils.h"
21 #include "FLAC/assert.h"
22 #include "FLAC/file_decoder.h"
23 #include "FLAC/metadata.h"
24 #include "share/grabbag.h"
25 #include <stdio.h>
26 #include <stdlib.h> /* for malloc() */
27
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 ******************************************************************************/
38
39 typedef struct {
40         FLAC__bool error_occurred;
41 } decoder_client_struct;
42
43 typedef struct {
44         FLAC__StreamMetadata *blocks[64];
45         unsigned num_blocks;
46 } our_metadata_struct;
47
48 static const char *flacfile_ = "metadata.flac";
49
50 /* our copy of the metadata in flacfile_ */
51 static our_metadata_struct our_metadata_;
52
53 /* the current block number that corresponds to the position of the iterator we are testing */
54 static unsigned mc_our_block_number_ = 0;
55
56 static FLAC__bool die_(const char *msg)
57 {
58         printf("ERROR: %s\n", msg);
59         return false;
60 }
61
62 static FLAC__bool die_c_(const char *msg, FLAC__Metadata_ChainStatus status)
63 {
64         printf("ERROR: %s\n", msg);
65         printf("       status=%s\n", FLAC__Metadata_ChainStatusString[status]);
66         return false;
67 }
68
69 static FLAC__bool die_ss_(const char *msg, FLAC__Metadata_SimpleIterator *iterator)
70 {
71         printf("ERROR: %s\n", msg);
72         printf("       status=%s\n", FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iterator)]);
73         return false;
74 }
75
76 static void *malloc_or_die_(size_t size)
77 {
78         void *x = malloc(size);
79         if(0 == x) {
80                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
81                 exit(1);
82         }
83         return x;
84 }
85
86 /* functions for working with our metadata copy */
87
88 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
89 {
90         unsigned i;
91         FLAC__StreamMetadata *obj = block;
92         FLAC__ASSERT(position < our_metadata_.num_blocks);
93         if(copy) {
94                 if(0 == (obj = FLAC__metadata_object_clone(block)))
95                         return die_("during FLAC__metadata_object_clone()");
96         }
97         FLAC__metadata_object_delete(our_metadata_.blocks[position]);
98         our_metadata_.blocks[position] = obj;
99
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;
104
105         return true;
106 }
107
108 static FLAC__bool insert_to_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
109 {
110         unsigned i;
111         FLAC__StreamMetadata *obj = block;
112         if(copy) {
113                 if(0 == (obj = FLAC__metadata_object_clone(block)))
114                         return die_("during FLAC__metadata_object_clone()");
115         }
116         if(position > our_metadata_.num_blocks) {
117                 position = our_metadata_.num_blocks;
118         }
119         else {
120                 for(i = our_metadata_.num_blocks; i > position; i--)
121                         our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
122         }
123         our_metadata_.blocks[position] = obj;
124         our_metadata_.num_blocks++;
125
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;
130
131         return true;
132 }
133
134 static void delete_from_our_metadata_(unsigned position)
135 {
136         unsigned i;
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--;
142
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;
148         }
149 }
150
151 /* function for comparing our metadata to a FLAC__Metadata_Chain */
152
153 static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
154 {
155         unsigned i;
156         FLAC__Metadata_Iterator *iterator;
157         FLAC__StreamMetadata *block;
158         FLAC__bool next_ok = true;
159
160         FLAC__ASSERT(0 != chain);
161
162         printf("\tcomparing chain... ");
163         fflush(stdout);
164
165         if(0 == (iterator = FLAC__metadata_iterator_new()))
166                 return die_("allocating memory for iterator");
167
168         FLAC__metadata_iterator_init(iterator, chain);
169
170         i = 0;
171         do {
172                 printf("%u... ", i);
173                 fflush(stdout);
174
175                 if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
176                         FLAC__metadata_iterator_delete(iterator);
177                         return die_("getting block from iterator");
178                 }
179
180                 if(!compare_block_(our_metadata_.blocks[i], block)) {
181                         FLAC__metadata_iterator_delete(iterator);
182                         return die_("metadata block mismatch");
183                 }
184
185                 i++;
186                 next_ok = FLAC__metadata_iterator_next(iterator);
187         } while(i < our_metadata_.num_blocks && next_ok);
188
189         FLAC__metadata_iterator_delete(iterator);
190
191         if(next_ok)
192                 return die_("chain has more blocks than expected");
193
194         if(i < our_metadata_.num_blocks)
195                 return die_("short block count in chain");
196
197         if(0 != current_block) {
198                 printf("CURRENT_POSITION... ");
199                 fflush(stdout);
200
201                 if(!compare_block_(our_metadata_.blocks[current_position], current_block))
202                         return die_("metadata block mismatch");
203         }
204
205         printf("PASSED\n");
206
207         return true;
208 }
209
210 /* decoder callbacks for checking the file */
211
212 static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
213 {
214         (void)decoder, (void)buffer, (void)client_data;
215
216         if(
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)
219         ) {
220                 printf("content... ");
221                 fflush(stdout);
222         }
223
224         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
225 }
226
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)
229 {
230         (void)decoder, (void)metadata, (void)client_data;
231
232         printf("%d... ", mc_our_block_number_);
233         fflush(stdout);
234
235         mc_our_block_number_++;
236 }
237
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)
240 {
241         decoder_client_struct *dcd = (decoder_client_struct*)client_data;
242
243         (void)decoder;
244
245         /* don't bother checking if we've already hit an error */
246         if(dcd->error_occurred)
247                 return;
248
249         printf("%d... ", mc_our_block_number_);
250         fflush(stdout);
251
252         if(mc_our_block_number_ >= our_metadata_.num_blocks) {
253                 (void)die_("got more metadata blocks than expected");
254                 dcd->error_occurred = true;
255         }
256         else {
257                 if(!compare_block_(our_metadata_.blocks[mc_our_block_number_], metadata)) {
258                         (void)die_("metadata block mismatch");
259                         dcd->error_occurred = true;
260                 }
261         }
262         mc_our_block_number_++;
263 }
264
265 static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
266 {
267         decoder_client_struct *dcd = (decoder_client_struct*)client_data;
268         (void)decoder;
269
270         dcd->error_occurred = true;
271         printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
272 }
273
274 static FLAC__bool generate_file_()
275 {
276         FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
277         FLAC__StreamMetadata *metadata[1];
278
279         printf("generating FLAC file for test\n");
280
281         while(our_metadata_.num_blocks > 0)
282                 delete_from_our_metadata_(0);
283
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);
296
297         {
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;
307         }
308
309         padding.is_last = true;
310         padding.type = FLAC__METADATA_TYPE_PADDING;
311         padding.length = 1234;
312
313         metadata[0] = &padding;
314
315         if(
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)
319         )
320                 return die_("priming our metadata");
321
322         if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
323                 return die_("creating the encoded file");
324
325         free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
326
327         return true;
328 }
329
330 static FLAC__bool test_file_(const char *filename, void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data))
331 {
332         FLAC__FileDecoder *decoder;
333         decoder_client_struct decoder_client_data;
334
335         FLAC__ASSERT(0 != filename);
336         FLAC__ASSERT(0 != metadata_callback);
337
338         mc_our_block_number_ = 0;
339         decoder_client_data.error_occurred = false;
340
341         printf("\ttesting '%s'... ", filename);
342         fflush(stdout);
343
344         if(0 == (decoder = FLAC__file_decoder_new()))
345                 return die_("couldn't allocate decoder instance");
346
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");
358         }
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");
363         }
364
365         FLAC__file_decoder_finish(decoder);
366         FLAC__file_decoder_delete(decoder);
367
368         if(decoder_client_data.error_occurred)
369                 return false;
370
371         if(mc_our_block_number_ != our_metadata_.num_blocks)
372                 return die_("short metadata block count");
373
374         printf("PASSED\n");
375         return true;
376 }
377
378 static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
379 {
380         if(!grabbag__file_change_stats(filename, read_only))
381                 return die_("during grabbag__file_change_stats()");
382
383         return true;
384 }
385
386 static FLAC__bool remove_file_(const char *filename)
387 {
388         while(our_metadata_.num_blocks > 0)
389                 delete_from_our_metadata_(0);
390
391         if(!grabbag__file_remove_file(filename))
392                 return die_("removing file");
393
394         return true;
395 }
396
397 static FLAC__bool test_level_0_()
398 {
399         FLAC__StreamMetadata streaminfo;
400
401         printf("\n\n++++++ testing level 0 interface\n");
402
403         if(!generate_file_())
404                 return false;
405
406         if(!test_file_(flacfile_, decoder_metadata_callback_null_))
407                 return false;
408
409         if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
410                 return die_("during FLAC__metadata_get_streaminfo()");
411
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");
423
424         if(!remove_file_(flacfile_))
425                 return false;
426
427         return true;
428 }
429
430 static FLAC__bool test_level_1_()
431 {
432         FLAC__Metadata_SimpleIterator *iterator;
433         FLAC__StreamMetadata *block, *app, *padding;
434         FLAC__byte data[1000];
435         unsigned our_current_position = 0;
436
437         /* initialize 'data' to avoid Valgrind errors */
438         memset(data, 0, sizeof(data));
439
440         printf("\n\n++++++ testing level 1 interface\n");
441
442         /************************************************************/
443
444         printf("simple iterator on read-only file\n");
445
446         if(!generate_file_())
447                 return false;
448
449         if(!change_stats_(flacfile_, /*read_only=*/true))
450                 return false;
451
452         if(!test_file_(flacfile_, decoder_metadata_callback_null_))
453                 return false;
454
455         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
456                 return die_("FLAC__metadata_simple_iterator_new()");
457
458         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
459                 return die_("FLAC__metadata_simple_iterator_init() returned false");
460
461         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
462         if(FLAC__metadata_simple_iterator_is_writable(iterator))
463                 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
464
465         printf("iterate forwards\n");
466
467         if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
468                 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
469         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
470                 return die_("getting block 0");
471         if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
472                 return die_("expected STREAMINFO type");
473         if(block->is_last)
474                 return die_("expected is_last to be false");
475         if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
476                 return die_("bad STREAMINFO length");
477         /* check to see if some basic data matches (c.f. generate_file_()) */
478         if(block->data.stream_info.channels != 1)
479                 return die_("mismatch in channels");
480         if(block->data.stream_info.bits_per_sample != 8)
481                 return die_("mismatch in bits_per_sample");
482         if(block->data.stream_info.sample_rate != 44100)
483                 return die_("mismatch in sample_rate");
484         if(block->data.stream_info.min_blocksize != 576)
485                 return die_("mismatch in min_blocksize");
486         if(block->data.stream_info.max_blocksize != 576)
487                 return die_("mismatch in max_blocksize");
488         FLAC__metadata_object_delete(block);
489
490         if(!FLAC__metadata_simple_iterator_next(iterator))
491                 return die_("forward iterator ended early");
492         our_current_position++;
493
494         if(!FLAC__metadata_simple_iterator_next(iterator))
495                 return die_("forward iterator ended early");
496         our_current_position++;
497
498         if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
499                 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
500         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
501                 return die_("getting block 2");
502         if(block->type != FLAC__METADATA_TYPE_PADDING)
503                 return die_("expected PADDING type");
504         if(!block->is_last)
505                 return die_("expected is_last to be true");
506         /* check to see if some basic data matches (c.f. generate_file_()) */
507         if(block->length != 1234)
508                 return die_("bad PADDING length");
509         FLAC__metadata_object_delete(block);
510
511         if(FLAC__metadata_simple_iterator_next(iterator))
512                 return die_("forward iterator returned true but should have returned false");
513
514         printf("iterate backwards\n");
515         if(!FLAC__metadata_simple_iterator_prev(iterator))
516                 return die_("reverse iterator ended early");
517         if(!FLAC__metadata_simple_iterator_prev(iterator))
518                 return die_("reverse iterator ended early");
519         if(FLAC__metadata_simple_iterator_prev(iterator))
520                 return die_("reverse iterator returned true but should have returned false");
521
522         printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
523
524         if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
525                 printf("PASSED.  FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
526         else
527                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
528
529         FLAC__metadata_simple_iterator_delete(iterator);
530
531         /************************************************************/
532
533         printf("simple iterator on writable file\n");
534
535         if(!change_stats_(flacfile_, /*read-only=*/false))
536                 return false;
537
538         printf("creating APPLICATION block\n");
539
540         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
541                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
542         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
543
544         printf("creating PADDING block\n");
545
546         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
547                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
548         padding->length = 20;
549
550         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
551                 return die_("FLAC__metadata_simple_iterator_new()");
552
553         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
554                 return die_("FLAC__metadata_simple_iterator_init() returned false");
555         our_current_position = 0;
556
557         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
558
559         printf("[S]VP\ttry to write over STREAMINFO block...\n");
560         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
561                 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
562         else
563                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
564
565         printf("[S]VP\tnext\n");
566         if(!FLAC__metadata_simple_iterator_next(iterator))
567                 return die_("iterator ended early\n");
568         our_current_position++;
569
570         printf("S[V]P\tnext\n");
571         if(!FLAC__metadata_simple_iterator_next(iterator))
572                 return die_("iterator ended early\n");
573         our_current_position++;
574
575         printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
576         padding->length = 25;
577         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
578                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
579         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
580                 return false;
581
582         printf("SVP[P]\tprev\n");
583         if(!FLAC__metadata_simple_iterator_prev(iterator))
584                 return die_("iterator ended early\n");
585         our_current_position--;
586
587         printf("SV[P]P\tprev\n");
588         if(!FLAC__metadata_simple_iterator_prev(iterator))
589                 return die_("iterator ended early\n");
590         our_current_position--;
591
592         printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
593         padding->length = 30;
594         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
595                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
596         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
597                 return false;
598
599         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
600                 return false;
601
602         printf("SV[P]PP\tprev\n");
603         if(!FLAC__metadata_simple_iterator_prev(iterator))
604                 return die_("iterator ended early\n");
605         our_current_position--;
606
607         printf("S[V]PPP\tprev\n");
608         if(!FLAC__metadata_simple_iterator_prev(iterator))
609                 return die_("iterator ended early\n");
610         our_current_position--;
611
612         printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
613         if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
614                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
615
616         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
617                 return false;
618
619         printf("[S]VPPP\tnext\n");
620         if(!FLAC__metadata_simple_iterator_next(iterator))
621                 return die_("iterator ended early\n");
622         our_current_position++;
623
624         printf("S[V]PPP\tnext\n");
625         if(!FLAC__metadata_simple_iterator_next(iterator))
626                 return die_("iterator ended early\n");
627         our_current_position++;
628
629         printf("SV[P]PP\tdelete (middle block), replace with padding\n");
630         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
631                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
632         our_current_position--;
633
634         printf("S[V]PPP\tnext\n");
635         if(!FLAC__metadata_simple_iterator_next(iterator))
636                 return die_("iterator ended early\n");
637         our_current_position++;
638
639         printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
640         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
641                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
642         delete_from_our_metadata_(our_current_position--);
643
644         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
645                 return false;
646
647         printf("S[V]PP\tnext\n");
648         if(!FLAC__metadata_simple_iterator_next(iterator))
649                 return die_("iterator ended early\n");
650         our_current_position++;
651
652         printf("SV[P]P\tnext\n");
653         if(!FLAC__metadata_simple_iterator_next(iterator))
654                 return die_("iterator ended early\n");
655         our_current_position++;
656
657         printf("SVP[P]\tdelete (last block), replace with padding\n");
658         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
659                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
660         our_current_position--;
661
662         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
663                 return false;
664
665         printf("SV[P]P\tnext\n");
666         if(!FLAC__metadata_simple_iterator_next(iterator))
667                 return die_("iterator ended early\n");
668         our_current_position++;
669
670         printf("SVP[P]\tdelete (last block), don't replace with padding\n");
671         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
672                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
673         delete_from_our_metadata_(our_current_position--);
674
675         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
676                 return false;
677
678         printf("SV[P]\tprev\n");
679         if(!FLAC__metadata_simple_iterator_prev(iterator))
680                 return die_("iterator ended early\n");
681         our_current_position--;
682
683         printf("S[V]P\tprev\n");
684         if(!FLAC__metadata_simple_iterator_prev(iterator))
685                 return die_("iterator ended early\n");
686         our_current_position--;
687
688         printf("[S]VP\tset STREAMINFO (change sample rate)\n");
689         FLAC__ASSERT(our_current_position == 0);
690         block = FLAC__metadata_simple_iterator_get_block(iterator);
691         block->data.stream_info.sample_rate = 32000;
692         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
693                 return die_("copying object");
694         if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
695                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
696         FLAC__metadata_object_delete(block);
697
698         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
699                 return false;
700
701         printf("[S]VP\tnext\n");
702         if(!FLAC__metadata_simple_iterator_next(iterator))
703                 return die_("iterator ended early\n");
704         our_current_position++;
705
706         printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
707         app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
708         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
709                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
710         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
711                 return false;
712         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
713
714         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
715                 return false;
716
717         printf("SV[A]P\tnext\n");
718         if(!FLAC__metadata_simple_iterator_next(iterator))
719                 return die_("iterator ended early\n");
720         our_current_position++;
721
722         printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
723         app->data.application.id[0] = 'f'; /* twiddle the id */
724         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
725                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
726         if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
727                 return false;
728         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
729
730         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
731                 return false;
732
733         printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
734         app->data.application.id[0] = 'g'; /* twiddle the id */
735         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
736                 return die_("setting APPLICATION data");
737         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
738                 return die_("copying object");
739         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
740                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
741
742         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
743                 return false;
744
745         printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
746         app->data.application.id[0] = 'h'; /* twiddle the id */
747         if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
748                 return die_("setting APPLICATION data");
749         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
750                 return die_("copying object");
751         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
752                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
753
754         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
755                 return false;
756
757         printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
758         app->data.application.id[0] = 'i'; /* twiddle the id */
759         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
760                 return die_("setting APPLICATION data");
761         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
762                 return die_("copying object");
763         our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
764         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
765                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
766
767         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
768                 return false;
769
770         printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
771         app->data.application.id[0] = 'j'; /* twiddle the id */
772         if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
773                 return die_("setting APPLICATION data");
774         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
775                 return die_("copying object");
776         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
777                 return die_("copying object");
778         our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
779         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
780                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
781
782         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
783                 return false;
784
785         printf("SVA[A]PP\tnext\n");
786         if(!FLAC__metadata_simple_iterator_next(iterator))
787                 return die_("iterator ended early\n");
788         our_current_position++;
789
790         printf("SVAA[P]P\tnext\n");
791         if(!FLAC__metadata_simple_iterator_next(iterator))
792                 return die_("iterator ended early\n");
793         our_current_position++;
794
795         printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
796         padding->length = 5;
797         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
798                 return die_("copying object");
799         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
800                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
801
802         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
803                 return false;
804
805         printf("SVAAP[P]\tset APPLICATION (grow)\n");
806         app->data.application.id[0] = 'k'; /* twiddle the id */
807         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
808                 return die_("copying object");
809         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
810                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
811
812         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
813                 return false;
814
815         printf("SVAAP[A]\tset PADDING (equal)\n");
816         padding->length = 27;
817         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
818                 return die_("copying object");
819         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
820                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
821
822         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
823                 return false;
824
825         printf("SVAAP[P]\tprev\n");
826         if(!FLAC__metadata_simple_iterator_prev(iterator))
827                 return die_("iterator ended early\n");
828         our_current_position--;
829
830         printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
831         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
832                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
833         delete_from_our_metadata_(our_current_position--);
834
835         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
836                 return false;
837
838         printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
839         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
840                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
841         delete_from_our_metadata_(our_current_position--);
842
843         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
844                 return false;
845
846         printf("SV[A]P\tnext\n");
847         if(!FLAC__metadata_simple_iterator_next(iterator))
848                 return die_("iterator ended early\n");
849         our_current_position++;
850
851         printf("SVA[P]\tinsert PADDING after\n");
852         padding->length = 5;
853         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
854                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
855         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
856                 return false;
857
858         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
859                 return false;
860
861         printf("SVAP[P]\tprev\n");
862         if(!FLAC__metadata_simple_iterator_prev(iterator))
863                 return die_("iterator ended early\n");
864         our_current_position--;
865
866         printf("SVA[P]P\tprev\n");
867         if(!FLAC__metadata_simple_iterator_prev(iterator))
868                 return die_("iterator ended early\n");
869         our_current_position--;
870
871         printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
872         if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
873                 return die_("setting APPLICATION data");
874         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
875                 return die_("copying object");
876         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
877                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
878
879         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
880                 return false;
881
882         printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
883         if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
884                 return die_("setting APPLICATION data");
885         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
886                 return die_("copying object");
887         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
888                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
889
890         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
891                 return false;
892
893         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
894         if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
895                 return die_("setting APPLICATION data");
896         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
897                 return die_("copying object");
898         our_metadata_.blocks[our_current_position+1]->length = 0;
899         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
900                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
901
902         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
903                 return false;
904
905         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
906         if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
907                 return die_("setting APPLICATION data");
908         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
909                 return die_("copying object");
910         delete_from_our_metadata_(our_current_position+1);
911         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
912                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
913
914         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
915                 return false;
916
917         printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
918         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
919                 return die_("setting APPLICATION data");
920         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
921                 return die_("copying object");
922         delete_from_our_metadata_(our_current_position+1);
923         our_metadata_.blocks[our_current_position]->is_last = true;
924         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
925                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
926
927         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
928                 return false;
929
930         printf("SV[A]\tset PADDING (equal size)\n");
931         padding->length = app->length;
932         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
933                 return die_("copying object");
934         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
935                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
936
937         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
938                 return false;
939
940         printf("SV[P]\tinsert PADDING after\n");
941         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
942                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
943         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
944                 return false;
945
946         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
947                 return false;
948
949         printf("SVP[P]\tinsert PADDING after\n");
950         padding->length = 5;
951         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
952                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
953         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
954                 return false;
955
956         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
957                 return false;
958
959         printf("SVPP[P]\tprev\n");
960         if(!FLAC__metadata_simple_iterator_prev(iterator))
961                 return die_("iterator ended early\n");
962         our_current_position--;
963
964         printf("SVP[P]P\tprev\n");
965         if(!FLAC__metadata_simple_iterator_prev(iterator))
966                 return die_("iterator ended early\n");
967         our_current_position--;
968
969         printf("SV[P]PP\tprev\n");
970         if(!FLAC__metadata_simple_iterator_prev(iterator))
971                 return die_("iterator ended early\n");
972         our_current_position--;
973
974         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
975         if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
976                 return die_("setting APPLICATION data");
977         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
978                 return die_("copying object");
979         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
980                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
981
982         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
983                 return false;
984
985         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
986         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
987                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
988         delete_from_our_metadata_(our_current_position--);
989
990         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
991                 return false;
992
993         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
994         if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
995                 return die_("setting APPLICATION data");
996         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
997                 return die_("copying object");
998         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
999                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1000
1001         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1002                 return false;
1003
1004         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1005         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1006                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1007         delete_from_our_metadata_(our_current_position--);
1008
1009         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1010                 return false;
1011
1012         printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1013         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1014                 return die_("setting APPLICATION data");
1015         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1016                 return die_("copying object");
1017         delete_from_our_metadata_(our_current_position+1);
1018         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1019                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1020
1021         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1022                 return false;
1023
1024         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1025         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1026                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1027         delete_from_our_metadata_(our_current_position--);
1028
1029         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1030                 return false;
1031
1032         printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1033         if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1034                 return die_("setting APPLICATION data");
1035         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1036                 return die_("copying object");
1037         our_metadata_.blocks[our_current_position+1]->length = 0;
1038         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1039                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1040
1041         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1042                 return false;
1043
1044         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1045         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1046                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1047         delete_from_our_metadata_(our_current_position--);
1048
1049         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1050                 return false;
1051
1052         printf("S[V]PP\tnext\n");
1053         if(!FLAC__metadata_simple_iterator_next(iterator))
1054                 return die_("iterator ended early\n");
1055         our_current_position++;
1056
1057         printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1058         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1059                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1060         delete_from_our_metadata_(our_current_position--);
1061
1062         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1063                 return false;
1064
1065         printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1066         if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1067                 return die_("setting APPLICATION data");
1068         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1069                 return die_("copying object");
1070         delete_from_our_metadata_(our_current_position+1);
1071         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1072                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1073
1074         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1075                 return false;
1076
1077         printf("delete simple iterator\n");
1078
1079         FLAC__metadata_simple_iterator_delete(iterator);
1080
1081         FLAC__metadata_object_delete(app);
1082         FLAC__metadata_object_delete(padding);
1083
1084         if(!remove_file_(flacfile_))
1085                 return false;
1086
1087         return true;
1088 }
1089
1090 static FLAC__bool test_level_2_()
1091 {
1092         FLAC__Metadata_Iterator *iterator;
1093         FLAC__Metadata_Chain *chain;
1094         FLAC__StreamMetadata *block, *app, *padding;
1095         FLAC__byte data[2000];
1096         unsigned our_current_position;
1097
1098         /* initialize 'data' to avoid Valgrind errors */
1099         memset(data, 0, sizeof(data));
1100
1101         printf("\n\n++++++ testing level 2 interface\n");
1102
1103         printf("generate read-only file\n");
1104
1105         if(!generate_file_())
1106                 return false;
1107
1108         if(!change_stats_(flacfile_, /*read_only=*/true))
1109                 return false;
1110
1111         printf("create chain\n");
1112
1113         if(0 == (chain = FLAC__metadata_chain_new()))
1114                 return die_("allocating chain");
1115
1116         printf("read chain\n");
1117
1118         if(!FLAC__metadata_chain_read(chain, flacfile_))
1119                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1120
1121         printf("[S]VP\ttest initial metadata\n");
1122
1123         if(!compare_chain_(chain, 0, 0))
1124                 return false;
1125         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1126                 return false;
1127
1128         printf("switch file to read-write\n");
1129
1130         if(!change_stats_(flacfile_, /*read-only=*/false))
1131                 return false;
1132
1133         printf("create iterator\n");
1134         if(0 == (iterator = FLAC__metadata_iterator_new()))
1135                 return die_("allocating memory for iterator");
1136
1137         our_current_position = 0;
1138
1139         FLAC__metadata_iterator_init(iterator, chain);
1140
1141         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1142                 return die_("getting block from iterator");
1143
1144         FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1145
1146         printf("[S]VP\tmodify STREAMINFO, write\n");
1147
1148         block->data.stream_info.sample_rate = 32000;
1149         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1150                 return die_("copying object");
1151
1152         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/true))
1153                 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1154         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1155                 return false;
1156         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1157                 return false;
1158
1159         printf("[S]VP\tnext\n");
1160         if(!FLAC__metadata_iterator_next(iterator))
1161                 return die_("iterator ended early\n");
1162         our_current_position++;
1163
1164         printf("S[V]P\tnext\n");
1165         if(!FLAC__metadata_iterator_next(iterator))
1166                 return die_("iterator ended early\n");
1167         our_current_position++;
1168
1169         printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1170         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1171                 return die_("getting block from iterator");
1172         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1173                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1174         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1175         if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1176                 return die_("setting APPLICATION data");
1177         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1178                 return die_("copying object");
1179         if(!FLAC__metadata_iterator_set_block(iterator, app))
1180                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1181
1182         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1183                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1184         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1185                 return false;
1186         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1187                 return false;
1188
1189         printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1190         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1191                 return die_("copying object");
1192         if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1193                 return die_("setting APPLICATION data");
1194         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1195                 return die_("copying object");
1196         if(!FLAC__metadata_iterator_set_block(iterator, app))
1197                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1198
1199         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1200                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1201         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1202                 return false;
1203         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1204                 return false;
1205
1206         printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1207         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1208                 return die_("copying object");
1209         if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1210                 return die_("setting APPLICATION data");
1211         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1212                 return die_("copying object");
1213         if(!FLAC__metadata_iterator_set_block(iterator, app))
1214                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1215
1216         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1217                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1218         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1219                 return false;
1220         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1221                 return false;
1222
1223         printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1224         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1225                 return die_("copying object");
1226         if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1227                 return die_("setting APPLICATION data");
1228         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1229                 return die_("copying object");
1230         if(!FLAC__metadata_iterator_set_block(iterator, app))
1231                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1232
1233         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1234                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1235         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1236                 return false;
1237         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1238                 return false;
1239
1240         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1241         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1242                 return die_("copying object");
1243         if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1244                 return die_("setting APPLICATION data");
1245         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1246                 return die_("copying object");
1247         if(!FLAC__metadata_iterator_set_block(iterator, app))
1248                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1249
1250         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1251                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1252         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1253                 return false;
1254         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1255                 return false;
1256
1257         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1258         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1259                 return die_("creating PADDING block");
1260         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1261                 return die_("copying object");
1262         if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1263                 return die_("setting APPLICATION data");
1264         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1265                 return die_("copying object");
1266         padding->length = 0;
1267         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1268                 return die_("internal error");
1269         if(!FLAC__metadata_iterator_set_block(iterator, app))
1270                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1271
1272         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1273                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1274         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1275                 return false;
1276         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1277                 return false;
1278
1279         printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1280         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1281                 return die_("copying object");
1282         if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1283                 return die_("setting APPLICATION data");
1284         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1285                 return die_("copying object");
1286         our_metadata_.blocks[our_current_position+1]->length = 13;
1287         if(!FLAC__metadata_iterator_set_block(iterator, app))
1288                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1289
1290         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1291                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1292         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1293                 return false;
1294         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1295                 return false;
1296
1297         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1298         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1299                 return die_("copying object");
1300         if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1301                 return die_("setting APPLICATION data");
1302         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1303                 return die_("copying object");
1304         if(!FLAC__metadata_iterator_set_block(iterator, app))
1305                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1306
1307         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1308                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1309         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1310                 return false;
1311         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1312                 return false;
1313
1314         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1315         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1316                 return die_("copying object");
1317         if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1318                 return die_("setting APPLICATION data");
1319         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1320                 return die_("copying object");
1321         our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1322         if(!FLAC__metadata_iterator_set_block(iterator, app))
1323                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1324
1325         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1326                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1327         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1328                 return false;
1329         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1330                 return false;
1331
1332         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1333         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1334                 return die_("copying object");
1335         if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1336                 return die_("setting APPLICATION data");
1337         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1338                 return die_("copying object");
1339         delete_from_our_metadata_(our_current_position+1);
1340         if(!FLAC__metadata_iterator_set_block(iterator, app))
1341                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1342
1343         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1344                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1345         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1346                 return false;
1347         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1348                 return false;
1349
1350         printf("SV[A]\tprev\n");
1351         if(!FLAC__metadata_iterator_prev(iterator))
1352                 return die_("iterator ended early\n");
1353         our_current_position--;
1354
1355         printf("S[V]A\tprev\n");
1356         if(!FLAC__metadata_iterator_prev(iterator))
1357                 return die_("iterator ended early\n");
1358         our_current_position--;
1359
1360         printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1361         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1362                 return die_("creating PADDING block");
1363         padding->length = 30;
1364         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1365                 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1366         else
1367                 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1368
1369         printf("[S]VP\tnext\n");
1370         if(!FLAC__metadata_iterator_next(iterator))
1371                 return die_("iterator ended early\n");
1372         our_current_position++;
1373
1374         printf("S[V]A\tinsert PADDING after\n");
1375         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1376                 return die_("copying metadata");
1377         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1378                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1379
1380         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1381                 return false;
1382
1383         printf("SV[P]A\tinsert PADDING before\n");
1384         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1385                 return die_("creating PADDING block");
1386         padding->length = 17;
1387         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1388                 return die_("copying metadata");
1389         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1390                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1391
1392         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1393                 return false;
1394
1395         printf("SV[P]PA\tinsert PADDING before\n");
1396         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1397                 return die_("creating PADDING block");
1398         padding->length = 0;
1399         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1400                 return die_("copying metadata");
1401         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1402                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1403
1404         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1405                 return false;
1406
1407         printf("SV[P]PPA\tnext\n");
1408         if(!FLAC__metadata_iterator_next(iterator))
1409                 return die_("iterator ended early\n");
1410         our_current_position++;
1411
1412         printf("SVP[P]PA\tnext\n");
1413         if(!FLAC__metadata_iterator_next(iterator))
1414                 return die_("iterator ended early\n");
1415         our_current_position++;
1416
1417         printf("SVPP[P]A\tnext\n");
1418         if(!FLAC__metadata_iterator_next(iterator))
1419                 return die_("iterator ended early\n");
1420         our_current_position++;
1421
1422         printf("SVPPP[A]\tinsert PADDING after\n");
1423         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1424                 return die_("creating PADDING block");
1425         padding->length = 57;
1426         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1427                 return die_("copying metadata");
1428         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1429                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1430
1431         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1432                 return false;
1433
1434         printf("SVPPPA[P]\tinsert PADDING before\n");
1435         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1436                 return die_("creating PADDING block");
1437         padding->length = 99;
1438         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1439                 return die_("copying metadata");
1440         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1441                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1442
1443         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1444                 return false;
1445
1446         printf("delete iterator\n");
1447         FLAC__metadata_iterator_delete(iterator);
1448         our_current_position = 0;
1449
1450         printf("SVPPPAPP\tmerge padding\n");
1451         FLAC__metadata_chain_merge_padding(chain);
1452         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1453         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1454         our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1455         delete_from_our_metadata_(7);
1456         delete_from_our_metadata_(4);
1457         delete_from_our_metadata_(3);
1458
1459         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1460                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1461         if(!compare_chain_(chain, 0, 0))
1462                 return false;
1463         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1464                 return false;
1465
1466         printf("SVPAP\tsort padding\n");
1467         FLAC__metadata_chain_sort_padding(chain);
1468         our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1469         delete_from_our_metadata_(2);
1470
1471         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1472                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1473         if(!compare_chain_(chain, 0, 0))
1474                 return false;
1475         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1476                 return false;
1477
1478         printf("create iterator\n");
1479         if(0 == (iterator = FLAC__metadata_iterator_new()))
1480                 return die_("allocating memory for iterator");
1481
1482         our_current_position = 0;
1483
1484         FLAC__metadata_iterator_init(iterator, chain);
1485
1486         printf("[S]VAP\tnext\n");
1487         if(!FLAC__metadata_iterator_next(iterator))
1488                 return die_("iterator ended early\n");
1489         our_current_position++;
1490
1491         printf("S[V]AP\tnext\n");
1492         if(!FLAC__metadata_iterator_next(iterator))
1493                 return die_("iterator ended early\n");
1494         our_current_position++;
1495
1496         printf("SV[A]P\tdelete middle block, replace with padding\n");
1497         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1498                 return die_("creating PADDING block");
1499         padding->length = 71;
1500         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1501                 return die_("copying object");
1502         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1503                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1504
1505         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1506                 return false;
1507
1508         printf("S[V]PP\tnext\n");
1509         if(!FLAC__metadata_iterator_next(iterator))
1510                 return die_("iterator ended early\n");
1511         our_current_position++;
1512
1513         printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1514         delete_from_our_metadata_(our_current_position--);
1515         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1516                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1517
1518         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1519                 return false;
1520
1521         printf("S[V]P\tnext\n");
1522         if(!FLAC__metadata_iterator_next(iterator))
1523                 return die_("iterator ended early\n");
1524         our_current_position++;
1525
1526         printf("SV[P]\tdelete last block, replace with padding\n");
1527         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1528                 return die_("creating PADDING block");
1529         padding->length = 219;
1530         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1531                 return die_("copying object");
1532         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1533                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1534
1535         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1536                 return false;
1537
1538         printf("S[V]P\tnext\n");
1539         if(!FLAC__metadata_iterator_next(iterator))
1540                 return die_("iterator ended early\n");
1541         our_current_position++;
1542
1543         printf("SV[P]\tdelete last block, don't replace with padding\n");
1544         delete_from_our_metadata_(our_current_position--);
1545         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1546                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1547
1548         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1549                 return false;
1550
1551         printf("S[V]\tprev\n");
1552         if(!FLAC__metadata_iterator_prev(iterator))
1553                 return die_("iterator ended early\n");
1554         our_current_position--;
1555
1556         printf("[S]V\tdelete STREAMINFO block, should fail\n");
1557         if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1558                 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1559
1560         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1561                 return false;
1562
1563         printf("delete iterator\n");
1564         FLAC__metadata_iterator_delete(iterator);
1565         our_current_position = 0;
1566
1567         printf("SV\tmerge padding\n");
1568         FLAC__metadata_chain_merge_padding(chain);
1569
1570         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1571                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1572         if(!compare_chain_(chain, 0, 0))
1573                 return false;
1574         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1575                 return false;
1576
1577         printf("SV\tsort padding\n");
1578         FLAC__metadata_chain_sort_padding(chain);
1579
1580         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1581                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1582         if(!compare_chain_(chain, 0, 0))
1583                 return false;
1584         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1585                 return false;
1586
1587         printf("delete chain\n");
1588
1589         FLAC__metadata_chain_delete(chain);
1590
1591         if(!remove_file_(flacfile_))
1592                 return false;
1593
1594         return true;
1595 }
1596
1597 FLAC__bool test_metadata_file_manipulation()
1598 {
1599         printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1600
1601         our_metadata_.num_blocks = 0;
1602
1603         if(!test_level_0_())
1604                 return false;
1605
1606         if(!test_level_1_())
1607                 return false;
1608
1609         if(!test_level_2_())
1610                 return false;
1611
1612         return true;
1613 }