updates to work with new grabbag lib
[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         printf("\n\n++++++ testing level 1 interface\n");
438
439         /************************************************************/
440
441         printf("simple iterator on read-only file\n");
442
443         if(!generate_file_())
444                 return false;
445
446         if(!change_stats_(flacfile_, /*read_only=*/true))
447                 return false;
448
449         if(!test_file_(flacfile_, decoder_metadata_callback_null_))
450                 return false;
451
452         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
453                 return die_("FLAC__metadata_simple_iterator_new()");
454
455         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
456                 return die_("FLAC__metadata_simple_iterator_init() returned false");
457
458         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
459         if(FLAC__metadata_simple_iterator_is_writable(iterator))
460                 return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
461
462         printf("iterate forwards\n");
463
464         if(FLAC__metadata_simple_iterator_get_block_type(iterator) != FLAC__METADATA_TYPE_STREAMINFO)
465                 return die_("expected STREAMINFO type from FLAC__metadata_simple_iterator_get_block_type()");
466         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
467                 return die_("getting block 0");
468         if(block->type != FLAC__METADATA_TYPE_STREAMINFO)
469                 return die_("expected STREAMINFO type");
470         if(block->is_last)
471                 return die_("expected is_last to be false");
472         if(block->length != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
473                 return die_("bad STREAMINFO length");
474         /* check to see if some basic data matches (c.f. generate_file_()) */
475         if(block->data.stream_info.channels != 1)
476                 return die_("mismatch in channels");
477         if(block->data.stream_info.bits_per_sample != 8)
478                 return die_("mismatch in bits_per_sample");
479         if(block->data.stream_info.sample_rate != 44100)
480                 return die_("mismatch in sample_rate");
481         if(block->data.stream_info.min_blocksize != 576)
482                 return die_("mismatch in min_blocksize");
483         if(block->data.stream_info.max_blocksize != 576)
484                 return die_("mismatch in max_blocksize");
485
486         if(!FLAC__metadata_simple_iterator_next(iterator))
487                 return die_("forward iterator ended early");
488         our_current_position++;
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_get_block_type(iterator) != FLAC__METADATA_TYPE_PADDING)
495                 return die_("expected PADDING type from FLAC__metadata_simple_iterator_get_block_type()");
496         if(0 == (block = FLAC__metadata_simple_iterator_get_block(iterator)))
497                 return die_("getting block 2");
498         if(block->type != FLAC__METADATA_TYPE_PADDING)
499                 return die_("expected PADDING type");
500         if(!block->is_last)
501                 return die_("expected is_last to be true");
502         /* check to see if some basic data matches (c.f. generate_file_()) */
503         if(block->length != 1234)
504                 return die_("bad PADDING length");
505
506         if(FLAC__metadata_simple_iterator_next(iterator))
507                 return die_("forward iterator returned true but should have returned false");
508
509         printf("iterate backwards\n");
510         if(!FLAC__metadata_simple_iterator_prev(iterator))
511                 return die_("reverse iterator ended early");
512         if(!FLAC__metadata_simple_iterator_prev(iterator))
513                 return die_("reverse iterator ended early");
514         if(FLAC__metadata_simple_iterator_prev(iterator))
515                 return die_("reverse iterator returned true but should have returned false");
516
517         printf("testing FLAC__metadata_simple_iterator_set_block() on read-only file...\n");
518
519         if(!FLAC__metadata_simple_iterator_set_block(iterator, (FLAC__StreamMetadata*)99, false))
520                 printf("PASSED.  FLAC__metadata_simple_iterator_set_block() returned false like it should\n");
521         else
522                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
523
524         FLAC__metadata_simple_iterator_delete(iterator);
525
526         /************************************************************/
527
528         printf("simple iterator on writable file\n");
529
530         if(!change_stats_(flacfile_, /*read-only=*/false))
531                 return false;
532
533         printf("creating APPLICATION block\n");
534
535         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
536                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
537         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
538
539         printf("creating PADDING block\n");
540
541         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
542                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)");
543         padding->length = 20;
544
545         if(0 == (iterator = FLAC__metadata_simple_iterator_new()))
546                 return die_("FLAC__metadata_simple_iterator_new()");
547
548         if(!FLAC__metadata_simple_iterator_init(iterator, flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
549                 return die_("FLAC__metadata_simple_iterator_init() returned false");
550         our_current_position = 0;
551
552         printf("is writable = %u\n", (unsigned)FLAC__metadata_simple_iterator_is_writable(iterator));
553
554         printf("[S]VP\ttry to write over STREAMINFO block...\n");
555         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
556                 printf("\tFLAC__metadata_simple_iterator_set_block() returned false like it should\n");
557         else
558                 return die_("FLAC__metadata_simple_iterator_set_block() returned true but shouldn't have");
559
560         printf("[S]VP\tnext\n");
561         if(!FLAC__metadata_simple_iterator_next(iterator))
562                 return die_("iterator ended early\n");
563         our_current_position++;
564
565         printf("S[V]P\tnext\n");
566         if(!FLAC__metadata_simple_iterator_next(iterator))
567                 return die_("iterator ended early\n");
568         our_current_position++;
569
570         printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
571         padding->length = 25;
572         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
573                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
574         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
575                 return false;
576
577         printf("SVP[P]\tprev\n");
578         if(!FLAC__metadata_simple_iterator_prev(iterator))
579                 return die_("iterator ended early\n");
580         our_current_position--;
581
582         printf("SV[P]P\tprev\n");
583         if(!FLAC__metadata_simple_iterator_prev(iterator))
584                 return die_("iterator ended early\n");
585         our_current_position--;
586
587         printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
588         padding->length = 30;
589         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
590                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
591         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
592                 return false;
593
594         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
595                 return false;
596
597         printf("SV[P]PP\tprev\n");
598         if(!FLAC__metadata_simple_iterator_prev(iterator))
599                 return die_("iterator ended early\n");
600         our_current_position--;
601
602         printf("S[V]PPP\tprev\n");
603         if(!FLAC__metadata_simple_iterator_prev(iterator))
604                 return die_("iterator ended early\n");
605         our_current_position--;
606
607         printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
608         if(FLAC__metadata_simple_iterator_delete_block(iterator, false))
609                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false) should have returned false", iterator);
610
611         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
612                 return false;
613
614         printf("[S]VPPP\tnext\n");
615         if(!FLAC__metadata_simple_iterator_next(iterator))
616                 return die_("iterator ended early\n");
617         our_current_position++;
618
619         printf("S[V]PPP\tnext\n");
620         if(!FLAC__metadata_simple_iterator_next(iterator))
621                 return die_("iterator ended early\n");
622         our_current_position++;
623
624         printf("SV[P]PP\tdelete (middle block), replace with padding\n");
625         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
626                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, true)", iterator);
627         our_current_position--;
628
629         printf("S[V]PPP\tnext\n");
630         if(!FLAC__metadata_simple_iterator_next(iterator))
631                 return die_("iterator ended early\n");
632         our_current_position++;
633
634         printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
635         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
636                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
637         delete_from_our_metadata_(our_current_position--);
638
639         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
640                 return false;
641
642         printf("S[V]PP\tnext\n");
643         if(!FLAC__metadata_simple_iterator_next(iterator))
644                 return die_("iterator ended early\n");
645         our_current_position++;
646
647         printf("SV[P]P\tnext\n");
648         if(!FLAC__metadata_simple_iterator_next(iterator))
649                 return die_("iterator ended early\n");
650         our_current_position++;
651
652         printf("SVP[P]\tdelete (last block), replace with padding\n");
653         if(!FLAC__metadata_simple_iterator_delete_block(iterator, true))
654                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
655         our_current_position--;
656
657         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
658                 return false;
659
660         printf("SV[P]P\tnext\n");
661         if(!FLAC__metadata_simple_iterator_next(iterator))
662                 return die_("iterator ended early\n");
663         our_current_position++;
664
665         printf("SVP[P]\tdelete (last block), don't replace with padding\n");
666         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
667                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
668         delete_from_our_metadata_(our_current_position--);
669
670         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
671                 return false;
672
673         printf("SV[P]\tprev\n");
674         if(!FLAC__metadata_simple_iterator_prev(iterator))
675                 return die_("iterator ended early\n");
676         our_current_position--;
677
678         printf("S[V]P\tprev\n");
679         if(!FLAC__metadata_simple_iterator_prev(iterator))
680                 return die_("iterator ended early\n");
681         our_current_position--;
682
683         printf("[S]VP\tset STREAMINFO (change sample rate)\n");
684         FLAC__ASSERT(our_current_position == 0);
685         block = FLAC__metadata_simple_iterator_get_block(iterator);
686         block->data.stream_info.sample_rate = 32000;
687         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
688                 return die_("copying object");
689         if(!FLAC__metadata_simple_iterator_set_block(iterator, block, false))
690                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, block, false)", iterator);
691         FLAC__metadata_object_delete(block);
692
693         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
694                 return false;
695
696         printf("[S]VP\tnext\n");
697         if(!FLAC__metadata_simple_iterator_next(iterator))
698                 return die_("iterator ended early\n");
699         our_current_position++;
700
701         printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
702         app->data.application.id[0] = 'e'; /* twiddle the id so that our comparison doesn't miss transposition */
703         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
704                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
705         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
706                 return false;
707         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
708
709         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
710                 return false;
711
712         printf("SV[A]P\tnext\n");
713         if(!FLAC__metadata_simple_iterator_next(iterator))
714                 return die_("iterator ended early\n");
715         our_current_position++;
716
717         printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
718         app->data.application.id[0] = 'f'; /* twiddle the id */
719         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
720                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
721         if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
722                 return false;
723         our_metadata_.blocks[our_current_position+1]->length -= (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + app->length;
724
725         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
726                 return false;
727
728         printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
729         app->data.application.id[0] = 'g'; /* twiddle the id */
730         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
731                 return die_("setting APPLICATION data");
732         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
733                 return die_("copying object");
734         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
735                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
736
737         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
738                 return false;
739
740         printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
741         app->data.application.id[0] = 'h'; /* twiddle the id */
742         if(!FLAC__metadata_object_application_set_data(app, data, 12, true))
743                 return die_("setting APPLICATION data");
744         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
745                 return die_("copying object");
746         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
747                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
748
749         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
750                 return false;
751
752         printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
753         app->data.application.id[0] = 'i'; /* twiddle the id */
754         if(!FLAC__metadata_object_application_set_data(app, data, sizeof(data), true))
755                 return die_("setting APPLICATION data");
756         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
757                 return die_("copying object");
758         our_metadata_.blocks[our_current_position+1]->length -= (sizeof(data) - 12);
759         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
760                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
761
762         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
763                 return false;
764
765         printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
766         app->data.application.id[0] = 'j'; /* twiddle the id */
767         if(!FLAC__metadata_object_application_set_data(app, data, 23, true))
768                 return die_("setting APPLICATION data");
769         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
770                 return die_("copying object");
771         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
772                 return die_("copying object");
773         our_metadata_.blocks[our_current_position+1]->length = sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH;
774         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
775                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
776
777         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
778                 return false;
779
780         printf("SVA[A]PP\tnext\n");
781         if(!FLAC__metadata_simple_iterator_next(iterator))
782                 return die_("iterator ended early\n");
783         our_current_position++;
784
785         printf("SVAA[P]P\tnext\n");
786         if(!FLAC__metadata_simple_iterator_next(iterator))
787                 return die_("iterator ended early\n");
788         our_current_position++;
789
790         printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
791         padding->length = 5;
792         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
793                 return die_("copying object");
794         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
795                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
796
797         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
798                 return false;
799
800         printf("SVAAP[P]\tset APPLICATION (grow)\n");
801         app->data.application.id[0] = 'k'; /* twiddle the id */
802         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
803                 return die_("copying object");
804         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, false))
805                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, false)", iterator);
806
807         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
808                 return false;
809
810         printf("SVAAP[A]\tset PADDING (equal)\n");
811         padding->length = 27;
812         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
813                 return die_("copying object");
814         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false))
815                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, false)", iterator);
816
817         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
818                 return false;
819
820         printf("SVAAP[P]\tprev\n");
821         if(!FLAC__metadata_simple_iterator_prev(iterator))
822                 return die_("iterator ended early\n");
823         our_current_position--;
824
825         printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
826         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
827                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
828         delete_from_our_metadata_(our_current_position--);
829
830         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
831                 return false;
832
833         printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
834         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
835                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
836         delete_from_our_metadata_(our_current_position--);
837
838         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
839                 return false;
840
841         printf("SV[A]P\tnext\n");
842         if(!FLAC__metadata_simple_iterator_next(iterator))
843                 return die_("iterator ended early\n");
844         our_current_position++;
845
846         printf("SVA[P]\tinsert PADDING after\n");
847         padding->length = 5;
848         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
849                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
850         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
851                 return false;
852
853         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
854                 return false;
855
856         printf("SVAP[P]\tprev\n");
857         if(!FLAC__metadata_simple_iterator_prev(iterator))
858                 return die_("iterator ended early\n");
859         our_current_position--;
860
861         printf("SVA[P]P\tprev\n");
862         if(!FLAC__metadata_simple_iterator_prev(iterator))
863                 return die_("iterator ended early\n");
864         our_current_position--;
865
866         printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
867         if(!FLAC__metadata_object_application_set_data(app, data, 32, true))
868                 return die_("setting APPLICATION data");
869         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
870                 return die_("copying object");
871         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
872                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
873
874         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
875                 return false;
876
877         printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
878         if(!FLAC__metadata_object_application_set_data(app, data, 60, true))
879                 return die_("setting APPLICATION data");
880         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
881                 return die_("copying object");
882         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
883                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
884
885         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
886                 return false;
887
888         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
889         if(!FLAC__metadata_object_application_set_data(app, data, 87, true))
890                 return die_("setting APPLICATION data");
891         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
892                 return die_("copying object");
893         our_metadata_.blocks[our_current_position+1]->length = 0;
894         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
895                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
896
897         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
898                 return false;
899
900         printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
901         if(!FLAC__metadata_object_application_set_data(app, data, 91, true))
902                 return die_("setting APPLICATION data");
903         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
904                 return die_("copying object");
905         delete_from_our_metadata_(our_current_position+1);
906         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
907                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
908
909         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
910                 return false;
911
912         printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
913         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
914                 return die_("setting APPLICATION data");
915         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
916                 return die_("copying object");
917         delete_from_our_metadata_(our_current_position+1);
918         our_metadata_.blocks[our_current_position]->is_last = true;
919         if(!FLAC__metadata_simple_iterator_set_block(iterator, app, true))
920                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, app, true)", iterator);
921
922         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
923                 return false;
924
925         printf("SV[A]\tset PADDING (equal size)\n");
926         padding->length = app->length;
927         if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
928                 return die_("copying object");
929         if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, true))
930                 return die_ss_("FLAC__metadata_simple_iterator_set_block(iterator, padding, true)", iterator);
931
932         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
933                 return false;
934
935         printf("SV[P]\tinsert PADDING after\n");
936         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
937                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
938         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
939                 return false;
940
941         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
942                 return false;
943
944         printf("SVP[P]\tinsert PADDING after\n");
945         padding->length = 5;
946         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false))
947                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, padding, false)", iterator);
948         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
949                 return false;
950
951         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
952                 return false;
953
954         printf("SVPP[P]\tprev\n");
955         if(!FLAC__metadata_simple_iterator_prev(iterator))
956                 return die_("iterator ended early\n");
957         our_current_position--;
958
959         printf("SVP[P]P\tprev\n");
960         if(!FLAC__metadata_simple_iterator_prev(iterator))
961                 return die_("iterator ended early\n");
962         our_current_position--;
963
964         printf("SV[P]PP\tprev\n");
965         if(!FLAC__metadata_simple_iterator_prev(iterator))
966                 return die_("iterator ended early\n");
967         our_current_position--;
968
969         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
970         if(!FLAC__metadata_object_application_set_data(app, data, 101, true))
971                 return die_("setting APPLICATION data");
972         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
973                 return die_("copying object");
974         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
975                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
976
977         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
978                 return false;
979
980         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
981         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
982                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
983         delete_from_our_metadata_(our_current_position--);
984
985         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
986                 return false;
987
988         printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
989         if(!FLAC__metadata_object_application_set_data(app, data, 97, true))
990                 return die_("setting APPLICATION data");
991         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
992                 return die_("copying object");
993         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
994                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
995
996         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
997                 return false;
998
999         printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1000         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1001                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1002         delete_from_our_metadata_(our_current_position--);
1003
1004         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1005                 return false;
1006
1007         printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1008         if(!FLAC__metadata_object_application_set_data(app, data, 100, true))
1009                 return die_("setting APPLICATION data");
1010         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1011                 return die_("copying object");
1012         delete_from_our_metadata_(our_current_position+1);
1013         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1014                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1015
1016         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1017                 return false;
1018
1019         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1020         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1021                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1022         delete_from_our_metadata_(our_current_position--);
1023
1024         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1025                 return false;
1026
1027         printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1028         if(!FLAC__metadata_object_application_set_data(app, data, 96, true))
1029                 return die_("setting APPLICATION data");
1030         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1031                 return die_("copying object");
1032         our_metadata_.blocks[our_current_position+1]->length = 0;
1033         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1034                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1035
1036         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1037                 return false;
1038
1039         printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1040         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1041                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1042         delete_from_our_metadata_(our_current_position--);
1043
1044         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1045                 return false;
1046
1047         printf("S[V]PP\tnext\n");
1048         if(!FLAC__metadata_simple_iterator_next(iterator))
1049                 return die_("iterator ended early\n");
1050         our_current_position++;
1051
1052         printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1053         if(!FLAC__metadata_simple_iterator_delete_block(iterator, false))
1054                 return die_ss_("FLAC__metadata_simple_iterator_delete_block(iterator, false)", iterator);
1055         delete_from_our_metadata_(our_current_position--);
1056
1057         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1058                 return false;
1059
1060         printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1061         if(!FLAC__metadata_object_application_set_data(app, data, 1, true))
1062                 return die_("setting APPLICATION data");
1063         if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1064                 return die_("copying object");
1065         delete_from_our_metadata_(our_current_position+1);
1066         if(!FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true))
1067                 return die_ss_("FLAC__metadata_simple_iterator_insert_block_after(iterator, app, true)", iterator);
1068
1069         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1070                 return false;
1071
1072         printf("delete simple iterator\n");
1073
1074         FLAC__metadata_simple_iterator_delete(iterator);
1075
1076         FLAC__metadata_object_delete(app);
1077         FLAC__metadata_object_delete(padding);
1078
1079         if(!remove_file_(flacfile_))
1080                 return false;
1081
1082         return true;
1083 }
1084
1085 static FLAC__bool test_level_2_()
1086 {
1087         FLAC__Metadata_Iterator *iterator;
1088         FLAC__Metadata_Chain *chain;
1089         FLAC__StreamMetadata *block, *app, *padding;
1090         FLAC__byte data[2000];
1091         unsigned our_current_position;
1092
1093         printf("\n\n++++++ testing level 2 interface\n");
1094
1095         printf("generate read-only file\n");
1096
1097         if(!generate_file_())
1098                 return false;
1099
1100         if(!change_stats_(flacfile_, /*read_only=*/true))
1101                 return false;
1102
1103         printf("create chain\n");
1104
1105         if(0 == (chain = FLAC__metadata_chain_new()))
1106                 return die_("allocating chain");
1107
1108         printf("read chain\n");
1109
1110         if(!FLAC__metadata_chain_read(chain, flacfile_))
1111                 return die_c_("reading chain", FLAC__metadata_chain_status(chain));
1112
1113         printf("[S]VP\ttest initial metadata\n");
1114
1115         if(!compare_chain_(chain, 0, 0))
1116                 return false;
1117         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1118                 return false;
1119
1120         printf("switch file to read-write\n");
1121
1122         if(!change_stats_(flacfile_, /*read-only=*/false))
1123                 return false;
1124
1125         printf("create iterator\n");
1126         if(0 == (iterator = FLAC__metadata_iterator_new()))
1127                 return die_("allocating memory for iterator");
1128
1129         our_current_position = 0;
1130
1131         FLAC__metadata_iterator_init(iterator, chain);
1132
1133         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1134                 return die_("getting block from iterator");
1135
1136         FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
1137
1138         printf("[S]VP\tmodify STREAMINFO, write\n");
1139
1140         block->data.stream_info.sample_rate = 32000;
1141         if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1142                 return die_("copying object");
1143
1144         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/true))
1145                 return die_c_("during FLAC__metadata_chain_write(chain, false, true)", FLAC__metadata_chain_status(chain));
1146         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1147                 return false;
1148         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1149                 return false;
1150
1151         printf("[S]VP\tnext\n");
1152         if(!FLAC__metadata_iterator_next(iterator))
1153                 return die_("iterator ended early\n");
1154         our_current_position++;
1155
1156         printf("S[V]P\tnext\n");
1157         if(!FLAC__metadata_iterator_next(iterator))
1158                 return die_("iterator ended early\n");
1159         our_current_position++;
1160
1161         printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1162         if(0 == (block = FLAC__metadata_iterator_get_block(iterator)))
1163                 return die_("getting block from iterator");
1164         if(0 == (app = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)))
1165                 return die_("FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)");
1166         memcpy(app->data.application.id, "duh", (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
1167         if(!FLAC__metadata_object_application_set_data(app, data, block->length-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1168                 return die_("setting APPLICATION data");
1169         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1170                 return die_("copying object");
1171         if(!FLAC__metadata_iterator_set_block(iterator, app))
1172                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1173
1174         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1175                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1176         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1177                 return false;
1178         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1179                 return false;
1180
1181         printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1182         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1183                 return die_("copying object");
1184         if(!FLAC__metadata_object_application_set_data(app, data, 26, true))
1185                 return die_("setting APPLICATION data");
1186         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1187                 return die_("copying object");
1188         if(!FLAC__metadata_iterator_set_block(iterator, app))
1189                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1190
1191         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1192                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1193         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1194                 return false;
1195         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1196                 return false;
1197
1198         printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1199         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1200                 return die_("copying object");
1201         if(!FLAC__metadata_object_application_set_data(app, data, 28, true))
1202                 return die_("setting APPLICATION data");
1203         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1204                 return die_("copying object");
1205         if(!FLAC__metadata_iterator_set_block(iterator, app))
1206                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1207
1208         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1209                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1210         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1211                 return false;
1212         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1213                 return false;
1214
1215         printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1216         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1217                 return die_("copying object");
1218         if(!FLAC__metadata_object_application_set_data(app, data, 36, true))
1219                 return die_("setting APPLICATION data");
1220         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1221                 return die_("copying object");
1222         if(!FLAC__metadata_iterator_set_block(iterator, app))
1223                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1224
1225         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1226                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1227         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1228                 return false;
1229         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1230                 return false;
1231
1232         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1233         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1234                 return die_("copying object");
1235         if(!FLAC__metadata_object_application_set_data(app, data, 33, true))
1236                 return die_("setting APPLICATION data");
1237         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1238                 return die_("copying object");
1239         if(!FLAC__metadata_iterator_set_block(iterator, app))
1240                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1241
1242         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1243                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1244         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1245                 return false;
1246         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1247                 return false;
1248
1249         printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1250         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1251                 return die_("creating PADDING block");
1252         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1253                 return die_("copying object");
1254         if(!FLAC__metadata_object_application_set_data(app, data, 29, true))
1255                 return die_("setting APPLICATION data");
1256         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1257                 return die_("copying object");
1258         padding->length = 0;
1259         if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1260                 return die_("internal error");
1261         if(!FLAC__metadata_iterator_set_block(iterator, app))
1262                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1263
1264         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1265                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1266         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1267                 return false;
1268         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1269                 return false;
1270
1271         printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1272         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1273                 return die_("copying object");
1274         if(!FLAC__metadata_object_application_set_data(app, data, 16, true))
1275                 return die_("setting APPLICATION data");
1276         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1277                 return die_("copying object");
1278         our_metadata_.blocks[our_current_position+1]->length = 13;
1279         if(!FLAC__metadata_iterator_set_block(iterator, app))
1280                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1281
1282         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1283                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1284         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1285                 return false;
1286         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1287                 return false;
1288
1289         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1290         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1291                 return die_("copying object");
1292         if(!FLAC__metadata_object_application_set_data(app, data, 50, true))
1293                 return die_("setting APPLICATION data");
1294         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1295                 return die_("copying object");
1296         if(!FLAC__metadata_iterator_set_block(iterator, app))
1297                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1298
1299         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1300                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1301         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1302                 return false;
1303         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1304                 return false;
1305
1306         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1307         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1308                 return die_("copying object");
1309         if(!FLAC__metadata_object_application_set_data(app, data, 56, true))
1310                 return die_("setting APPLICATION data");
1311         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1312                 return die_("copying object");
1313         our_metadata_.blocks[our_current_position+1]->length -= (56 - 50);
1314         if(!FLAC__metadata_iterator_set_block(iterator, app))
1315                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1316
1317         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1318                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1319         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1320                 return false;
1321         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1322                 return false;
1323
1324         printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1325         if(0 == (app = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1326                 return die_("copying object");
1327         if(!FLAC__metadata_object_application_set_data(app, data, 67, true))
1328                 return die_("setting APPLICATION data");
1329         if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1330                 return die_("copying object");
1331         delete_from_our_metadata_(our_current_position+1);
1332         if(!FLAC__metadata_iterator_set_block(iterator, app))
1333                 return die_c_("FLAC__metadata_iterator_set_block(iterator, app)", FLAC__metadata_chain_status(chain));
1334
1335         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1336                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1337         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1338                 return false;
1339         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1340                 return false;
1341
1342         printf("SV[A]\tprev\n");
1343         if(!FLAC__metadata_iterator_prev(iterator))
1344                 return die_("iterator ended early\n");
1345         our_current_position--;
1346
1347         printf("S[V]A\tprev\n");
1348         if(!FLAC__metadata_iterator_prev(iterator))
1349                 return die_("iterator ended early\n");
1350         our_current_position--;
1351
1352         printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1353         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1354                 return die_("creating PADDING block");
1355         padding->length = 30;
1356         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1357                 printf("\tFLAC__metadata_iterator_insert_block_before() returned false like it should\n");
1358         else
1359                 return die_("FLAC__metadata_iterator_insert_block_before() should have returned false");
1360
1361         printf("[S]VP\tnext\n");
1362         if(!FLAC__metadata_iterator_next(iterator))
1363                 return die_("iterator ended early\n");
1364         our_current_position++;
1365
1366         printf("S[V]A\tinsert PADDING after\n");
1367         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1368                 return die_("copying metadata");
1369         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1370                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1371
1372         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1373                 return false;
1374
1375         printf("SV[P]A\tinsert PADDING before\n");
1376         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1377                 return die_("creating PADDING block");
1378         padding->length = 17;
1379         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1380                 return die_("copying metadata");
1381         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1382                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1383
1384         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1385                 return false;
1386
1387         printf("SV[P]PA\tinsert PADDING before\n");
1388         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[our_current_position])))
1389                 return die_("creating PADDING block");
1390         padding->length = 0;
1391         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1392                 return die_("copying metadata");
1393         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1394                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1395
1396         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1397                 return false;
1398
1399         printf("SV[P]PPA\tnext\n");
1400         if(!FLAC__metadata_iterator_next(iterator))
1401                 return die_("iterator ended early\n");
1402         our_current_position++;
1403
1404         printf("SVP[P]PA\tnext\n");
1405         if(!FLAC__metadata_iterator_next(iterator))
1406                 return die_("iterator ended early\n");
1407         our_current_position++;
1408
1409         printf("SVPP[P]A\tnext\n");
1410         if(!FLAC__metadata_iterator_next(iterator))
1411                 return die_("iterator ended early\n");
1412         our_current_position++;
1413
1414         printf("SVPPP[A]\tinsert PADDING after\n");
1415         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1416                 return die_("creating PADDING block");
1417         padding->length = 57;
1418         if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1419                 return die_("copying metadata");
1420         if(!FLAC__metadata_iterator_insert_block_after(iterator, padding))
1421                 return die_("FLAC__metadata_iterator_insert_block_after(iterator, padding)");
1422
1423         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1424                 return false;
1425
1426         printf("SVPPPA[P]\tinsert PADDING before\n");
1427         if(0 == (padding = FLAC__metadata_object_clone(our_metadata_.blocks[2])))
1428                 return die_("creating PADDING block");
1429         padding->length = 99;
1430         if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1431                 return die_("copying metadata");
1432         if(!FLAC__metadata_iterator_insert_block_before(iterator, padding))
1433                 return die_("FLAC__metadata_iterator_insert_block_before(iterator, padding)");
1434
1435         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1436                 return false;
1437
1438         printf("delete iterator\n");
1439         FLAC__metadata_iterator_delete(iterator);
1440         our_current_position = 0;
1441
1442         printf("SVPPPAPP\tmerge padding\n");
1443         FLAC__metadata_chain_merge_padding(chain);
1444         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->length);
1445         our_metadata_.blocks[2]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->length);
1446         our_metadata_.blocks[6]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->length);
1447         delete_from_our_metadata_(7);
1448         delete_from_our_metadata_(4);
1449         delete_from_our_metadata_(3);
1450
1451         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1452                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1453         if(!compare_chain_(chain, 0, 0))
1454                 return false;
1455         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1456                 return false;
1457
1458         printf("SVPAP\tsort padding\n");
1459         FLAC__metadata_chain_sort_padding(chain);
1460         our_metadata_.blocks[4]->length += (FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->length);
1461         delete_from_our_metadata_(2);
1462
1463         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/false))
1464                 return die_c_("during FLAC__metadata_chain_write(chain, true, false)", FLAC__metadata_chain_status(chain));
1465         if(!compare_chain_(chain, 0, 0))
1466                 return false;
1467         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1468                 return false;
1469
1470         printf("create iterator\n");
1471         if(0 == (iterator = FLAC__metadata_iterator_new()))
1472                 return die_("allocating memory for iterator");
1473
1474         our_current_position = 0;
1475
1476         FLAC__metadata_iterator_init(iterator, chain);
1477
1478         printf("[S]VAP\tnext\n");
1479         if(!FLAC__metadata_iterator_next(iterator))
1480                 return die_("iterator ended early\n");
1481         our_current_position++;
1482
1483         printf("S[V]AP\tnext\n");
1484         if(!FLAC__metadata_iterator_next(iterator))
1485                 return die_("iterator ended early\n");
1486         our_current_position++;
1487
1488         printf("SV[A]P\tdelete middle block, replace with padding\n");
1489         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1490                 return die_("creating PADDING block");
1491         padding->length = 71;
1492         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1493                 return die_("copying object");
1494         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1495                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1496
1497         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1498                 return false;
1499
1500         printf("S[V]PP\tnext\n");
1501         if(!FLAC__metadata_iterator_next(iterator))
1502                 return die_("iterator ended early\n");
1503         our_current_position++;
1504
1505         printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1506         delete_from_our_metadata_(our_current_position--);
1507         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1508                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1509
1510         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1511                 return false;
1512
1513         printf("S[V]P\tnext\n");
1514         if(!FLAC__metadata_iterator_next(iterator))
1515                 return die_("iterator ended early\n");
1516         our_current_position++;
1517
1518         printf("SV[P]\tdelete last block, replace with padding\n");
1519         if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)))
1520                 return die_("creating PADDING block");
1521         padding->length = 219;
1522         if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1523                 return die_("copying object");
1524         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/true))
1525                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, true)", FLAC__metadata_chain_status(chain));
1526
1527         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1528                 return false;
1529
1530         printf("S[V]P\tnext\n");
1531         if(!FLAC__metadata_iterator_next(iterator))
1532                 return die_("iterator ended early\n");
1533         our_current_position++;
1534
1535         printf("SV[P]\tdelete last block, don't replace with padding\n");
1536         delete_from_our_metadata_(our_current_position--);
1537         if(!FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1538                 return die_c_("FLAC__metadata_iterator_delete_block(iterator, false)", FLAC__metadata_chain_status(chain));
1539
1540         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1541                 return false;
1542
1543         printf("S[V]\tprev\n");
1544         if(!FLAC__metadata_iterator_prev(iterator))
1545                 return die_("iterator ended early\n");
1546         our_current_position--;
1547
1548         printf("[S]V\tdelete STREAMINFO block, should fail\n");
1549         if(FLAC__metadata_iterator_delete_block(iterator, /*replace_with_padding=*/false))
1550                 return die_("FLAC__metadata_iterator_delete_block() on STREAMINFO should have failed but didn't");
1551
1552         if(!compare_chain_(chain, our_current_position, FLAC__metadata_iterator_get_block(iterator)))
1553                 return false;
1554
1555         printf("delete iterator\n");
1556         FLAC__metadata_iterator_delete(iterator);
1557         our_current_position = 0;
1558
1559         printf("SV\tmerge padding\n");
1560         FLAC__metadata_chain_merge_padding(chain);
1561
1562         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1563                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1564         if(!compare_chain_(chain, 0, 0))
1565                 return false;
1566         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1567                 return false;
1568
1569         printf("SV\tsort padding\n");
1570         FLAC__metadata_chain_sort_padding(chain);
1571
1572         if(!FLAC__metadata_chain_write(chain, /*use_padding=*/false, /*preserve_file_stats=*/false))
1573                 return die_c_("during FLAC__metadata_chain_write(chain, false, false)", FLAC__metadata_chain_status(chain));
1574         if(!compare_chain_(chain, 0, 0))
1575                 return false;
1576         if(!test_file_(flacfile_, decoder_metadata_callback_compare_))
1577                 return false;
1578
1579         printf("delete chain\n");
1580
1581         FLAC__metadata_chain_delete(chain);
1582
1583         if(!remove_file_(flacfile_))
1584                 return false;
1585
1586         return true;
1587 }
1588
1589 FLAC__bool test_metadata_file_manipulation()
1590 {
1591         printf("\n+++ libFLAC unit test: metadata manipulation\n\n");
1592
1593         our_metadata_.num_blocks = 0;
1594
1595         if(!test_level_0_())
1596                 return false;
1597
1598         if(!test_level_1_())
1599                 return false;
1600
1601         if(!test_level_2_())
1602                 return false;
1603
1604         return true;
1605 }