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