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