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