1*600f14f4SXin Li /* test_libFLAC++ - Unit tester for libFLAC++
2*600f14f4SXin Li * Copyright (C) 2002-2009 Josh Coalson
3*600f14f4SXin Li * Copyright (C) 2011-2023 Xiph.Org Foundation
4*600f14f4SXin Li *
5*600f14f4SXin Li * This program is free software; you can redistribute it and/or
6*600f14f4SXin Li * modify it under the terms of the GNU General Public License
7*600f14f4SXin Li * as published by the Free Software Foundation; either version 2
8*600f14f4SXin Li * of the License, or (at your option) any later version.
9*600f14f4SXin Li *
10*600f14f4SXin Li * This program is distributed in the hope that it will be useful,
11*600f14f4SXin Li * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*600f14f4SXin Li * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*600f14f4SXin Li * GNU General Public License for more details.
14*600f14f4SXin Li *
15*600f14f4SXin Li * You should have received a copy of the GNU General Public License along
16*600f14f4SXin Li * with this program; if not, write to the Free Software Foundation, Inc.,
17*600f14f4SXin Li * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18*600f14f4SXin Li */
19*600f14f4SXin Li
20*600f14f4SXin Li #ifdef HAVE_CONFIG_H
21*600f14f4SXin Li # include <config.h>
22*600f14f4SXin Li #endif
23*600f14f4SXin Li
24*600f14f4SXin Li #include <stdio.h>
25*600f14f4SXin Li #include <stdlib.h> /* for malloc() */
26*600f14f4SXin Li #include <string.h> /* for memcpy()/memset() */
27*600f14f4SXin Li #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
28*600f14f4SXin Li #ifdef _MSC_VER
29*600f14f4SXin Li #include <sys/utime.h>
30*600f14f4SXin Li #endif
31*600f14f4SXin Li #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
32*600f14f4SXin Li #include <unistd.h> /* for chown(), unlink() */
33*600f14f4SXin Li #endif
34*600f14f4SXin Li #include <sys/stat.h> /* for stat(), maybe chmod() */
35*600f14f4SXin Li #include "FLAC/assert.h"
36*600f14f4SXin Li #include "FLAC++/decoder.h"
37*600f14f4SXin Li #include "FLAC++/metadata.h"
38*600f14f4SXin Li #include "share/grabbag.h"
39*600f14f4SXin Li #include "share/compat.h"
40*600f14f4SXin Li #include "share/macros.h"
41*600f14f4SXin Li #include "share/safe_str.h"
42*600f14f4SXin Li extern "C" {
43*600f14f4SXin Li #include "test_libs_common/file_utils_flac.h"
44*600f14f4SXin Li }
45*600f14f4SXin Li
46*600f14f4SXin Li /******************************************************************************
47*600f14f4SXin Li The general strategy of these tests (for interface levels 1 and 2) is
48*600f14f4SXin Li to create a dummy FLAC file with a known set of initial metadata
49*600f14f4SXin Li blocks, then keep a mirror locally of what we expect the metadata to be
50*600f14f4SXin Li after each operation. Then testing becomes a simple matter of running
51*600f14f4SXin Li a FLAC::Decoder::File over the dummy file after each operation, comparing
52*600f14f4SXin Li the decoded metadata to what's in our local copy. If there are any
53*600f14f4SXin Li differences in the metadata, or the actual audio data is corrupted, we
54*600f14f4SXin Li will catch it while decoding.
55*600f14f4SXin Li ******************************************************************************/
56*600f14f4SXin Li
57*600f14f4SXin Li class OurFileDecoder: public FLAC::Decoder::File {
58*600f14f4SXin Li public:
OurFileDecoder(bool ignore_metadata)59*600f14f4SXin Li inline OurFileDecoder(bool ignore_metadata): ignore_metadata_(ignore_metadata), error_occurred_(false) { }
60*600f14f4SXin Li
61*600f14f4SXin Li bool ignore_metadata_;
62*600f14f4SXin Li bool error_occurred_;
63*600f14f4SXin Li protected:
64*600f14f4SXin Li ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
65*600f14f4SXin Li void metadata_callback(const ::FLAC__StreamMetadata *metadata);
66*600f14f4SXin Li void error_callback(::FLAC__StreamDecoderErrorStatus status);
67*600f14f4SXin Li };
68*600f14f4SXin Li
69*600f14f4SXin Li struct OurMetadata {
70*600f14f4SXin Li FLAC::Metadata::Prototype *blocks[64];
71*600f14f4SXin Li uint32_t num_blocks;
72*600f14f4SXin Li };
73*600f14f4SXin Li
74*600f14f4SXin Li /* our copy of the metadata in flacfilename() */
75*600f14f4SXin Li static OurMetadata our_metadata_;
76*600f14f4SXin Li
77*600f14f4SXin Li /* the current block number that corresponds to the position of the iterator we are testing */
78*600f14f4SXin Li static uint32_t mc_our_block_number_ = 0;
79*600f14f4SXin Li
flacfilename(bool is_ogg)80*600f14f4SXin Li static const char *flacfilename(bool is_ogg)
81*600f14f4SXin Li {
82*600f14f4SXin Li return is_ogg? "metadata.oga" : "metadata.flac";
83*600f14f4SXin Li }
84*600f14f4SXin Li
die_(const char * msg)85*600f14f4SXin Li static bool die_(const char *msg)
86*600f14f4SXin Li {
87*600f14f4SXin Li printf("ERROR: %s\n", msg);
88*600f14f4SXin Li return false;
89*600f14f4SXin Li }
90*600f14f4SXin Li
die_c_(const char * msg,FLAC::Metadata::Chain::Status status)91*600f14f4SXin Li static bool die_c_(const char *msg, FLAC::Metadata::Chain::Status status)
92*600f14f4SXin Li {
93*600f14f4SXin Li printf("ERROR: %s\n", msg);
94*600f14f4SXin Li printf(" status=%u (%s)\n", (uint32_t)((::FLAC__Metadata_ChainStatus)status), status.as_cstring());
95*600f14f4SXin Li return false;
96*600f14f4SXin Li }
97*600f14f4SXin Li
die_ss_(const char * msg,FLAC::Metadata::SimpleIterator & iterator)98*600f14f4SXin Li static bool die_ss_(const char *msg, FLAC::Metadata::SimpleIterator &iterator)
99*600f14f4SXin Li {
100*600f14f4SXin Li const FLAC::Metadata::SimpleIterator::Status status = iterator.status();
101*600f14f4SXin Li printf("ERROR: %s\n", msg);
102*600f14f4SXin Li printf(" status=%u (%s)\n", (uint32_t)((::FLAC__Metadata_SimpleIteratorStatus)status), status.as_cstring());
103*600f14f4SXin Li return false;
104*600f14f4SXin Li }
105*600f14f4SXin Li
malloc_or_die_(size_t size)106*600f14f4SXin Li static void *malloc_or_die_(size_t size)
107*600f14f4SXin Li {
108*600f14f4SXin Li void *x = malloc(size);
109*600f14f4SXin Li if(0 == x) {
110*600f14f4SXin Li fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (uint32_t)size);
111*600f14f4SXin Li exit(1);
112*600f14f4SXin Li }
113*600f14f4SXin Li return x;
114*600f14f4SXin Li }
115*600f14f4SXin Li
strdup_or_die_(const char * s)116*600f14f4SXin Li static char *strdup_or_die_(const char *s)
117*600f14f4SXin Li {
118*600f14f4SXin Li char *x = strdup(s);
119*600f14f4SXin Li if(0 == x) {
120*600f14f4SXin Li fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
121*600f14f4SXin Li exit(1);
122*600f14f4SXin Li }
123*600f14f4SXin Li return x;
124*600f14f4SXin Li }
125*600f14f4SXin Li
126*600f14f4SXin Li /* functions for working with our metadata copy */
127*600f14f4SXin Li
replace_in_our_metadata_(FLAC::Metadata::Prototype * block,uint32_t position,bool copy)128*600f14f4SXin Li static bool replace_in_our_metadata_(FLAC::Metadata::Prototype *block, uint32_t position, bool copy)
129*600f14f4SXin Li {
130*600f14f4SXin Li uint32_t i;
131*600f14f4SXin Li FLAC::Metadata::Prototype *obj = block;
132*600f14f4SXin Li FLAC__ASSERT(position < our_metadata_.num_blocks);
133*600f14f4SXin Li if(copy) {
134*600f14f4SXin Li if(0 == (obj = FLAC::Metadata::clone(block)))
135*600f14f4SXin Li return die_("during FLAC::Metadata::clone()");
136*600f14f4SXin Li }
137*600f14f4SXin Li delete our_metadata_.blocks[position];
138*600f14f4SXin Li our_metadata_.blocks[position] = obj;
139*600f14f4SXin Li
140*600f14f4SXin Li /* set the is_last flags */
141*600f14f4SXin Li for(i = 0; i < our_metadata_.num_blocks - 1; i++)
142*600f14f4SXin Li our_metadata_.blocks[i]->set_is_last(false);
143*600f14f4SXin Li our_metadata_.blocks[i]->set_is_last(true);
144*600f14f4SXin Li
145*600f14f4SXin Li return true;
146*600f14f4SXin Li }
147*600f14f4SXin Li
insert_to_our_metadata_(FLAC::Metadata::Prototype * block,uint32_t position,bool copy)148*600f14f4SXin Li static bool insert_to_our_metadata_(FLAC::Metadata::Prototype *block, uint32_t position, bool copy)
149*600f14f4SXin Li {
150*600f14f4SXin Li uint32_t i;
151*600f14f4SXin Li FLAC::Metadata::Prototype *obj = block;
152*600f14f4SXin Li if(copy) {
153*600f14f4SXin Li if(0 == (obj = FLAC::Metadata::clone(block)))
154*600f14f4SXin Li return die_("during FLAC::Metadata::clone()");
155*600f14f4SXin Li }
156*600f14f4SXin Li if(position > our_metadata_.num_blocks) {
157*600f14f4SXin Li position = our_metadata_.num_blocks;
158*600f14f4SXin Li }
159*600f14f4SXin Li else {
160*600f14f4SXin Li for(i = our_metadata_.num_blocks; i > position; i--)
161*600f14f4SXin Li our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
162*600f14f4SXin Li }
163*600f14f4SXin Li our_metadata_.blocks[position] = obj;
164*600f14f4SXin Li our_metadata_.num_blocks++;
165*600f14f4SXin Li
166*600f14f4SXin Li /* set the is_last flags */
167*600f14f4SXin Li for(i = 0; i < our_metadata_.num_blocks - 1; i++)
168*600f14f4SXin Li our_metadata_.blocks[i]->set_is_last(false);
169*600f14f4SXin Li our_metadata_.blocks[i]->set_is_last(true);
170*600f14f4SXin Li
171*600f14f4SXin Li return true;
172*600f14f4SXin Li }
173*600f14f4SXin Li
delete_from_our_metadata_(uint32_t position)174*600f14f4SXin Li static void delete_from_our_metadata_(uint32_t position)
175*600f14f4SXin Li {
176*600f14f4SXin Li uint32_t i;
177*600f14f4SXin Li FLAC__ASSERT(position < our_metadata_.num_blocks);
178*600f14f4SXin Li delete our_metadata_.blocks[position];
179*600f14f4SXin Li for(i = position; i < our_metadata_.num_blocks - 1; i++)
180*600f14f4SXin Li our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
181*600f14f4SXin Li our_metadata_.num_blocks--;
182*600f14f4SXin Li
183*600f14f4SXin Li /* set the is_last flags */
184*600f14f4SXin Li if(our_metadata_.num_blocks > 0) {
185*600f14f4SXin Li for(i = 0; i < our_metadata_.num_blocks - 1; i++)
186*600f14f4SXin Li our_metadata_.blocks[i]->set_is_last(false);
187*600f14f4SXin Li our_metadata_.blocks[i]->set_is_last(true);
188*600f14f4SXin Li }
189*600f14f4SXin Li }
190*600f14f4SXin Li
add_to_padding_length_(uint32_t indx,int delta)191*600f14f4SXin Li void add_to_padding_length_(uint32_t indx, int delta)
192*600f14f4SXin Li {
193*600f14f4SXin Li FLAC::Metadata::Padding *padding = dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[indx]);
194*600f14f4SXin Li FLAC__ASSERT(0 != padding);
195*600f14f4SXin Li padding->set_length((uint32_t)((int)padding->get_length() + delta));
196*600f14f4SXin Li }
197*600f14f4SXin Li
198*600f14f4SXin Li /*
199*600f14f4SXin Li * This wad of functions supports filename- and callback-based chain reading/writing.
200*600f14f4SXin Li * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
201*600f14f4SXin Li */
open_tempfile_(const char * filename,FILE ** tempfile,char ** tempfilename)202*600f14f4SXin Li bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
203*600f14f4SXin Li {
204*600f14f4SXin Li static const char *tempfile_suffix = ".metadata_edit";
205*600f14f4SXin Li size_t destlen = strlen(filename) + strlen(tempfile_suffix) + 1;
206*600f14f4SXin Li
207*600f14f4SXin Li *tempfilename = (char*)malloc(destlen);
208*600f14f4SXin Li if (*tempfilename == 0)
209*600f14f4SXin Li return false;
210*600f14f4SXin Li flac_snprintf(*tempfilename, destlen, "%s%s", filename, tempfile_suffix);
211*600f14f4SXin Li
212*600f14f4SXin Li *tempfile = flac_fopen(*tempfilename, "wb");
213*600f14f4SXin Li if (*tempfile == 0)
214*600f14f4SXin Li return false;
215*600f14f4SXin Li
216*600f14f4SXin Li return true;
217*600f14f4SXin Li }
218*600f14f4SXin Li
cleanup_tempfile_(FILE ** tempfile,char ** tempfilename)219*600f14f4SXin Li void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
220*600f14f4SXin Li {
221*600f14f4SXin Li if (*tempfile != 0) {
222*600f14f4SXin Li (void)fclose(*tempfile);
223*600f14f4SXin Li *tempfile = 0;
224*600f14f4SXin Li }
225*600f14f4SXin Li
226*600f14f4SXin Li if (*tempfilename != 0) {
227*600f14f4SXin Li (void)flac_unlink(*tempfilename);
228*600f14f4SXin Li free(*tempfilename);
229*600f14f4SXin Li *tempfilename = 0;
230*600f14f4SXin Li }
231*600f14f4SXin Li }
232*600f14f4SXin Li
transport_tempfile_(const char * filename,FILE ** tempfile,char ** tempfilename)233*600f14f4SXin Li bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
234*600f14f4SXin Li {
235*600f14f4SXin Li FLAC__ASSERT(0 != filename);
236*600f14f4SXin Li FLAC__ASSERT(0 != tempfile);
237*600f14f4SXin Li FLAC__ASSERT(0 != tempfilename);
238*600f14f4SXin Li FLAC__ASSERT(0 != *tempfilename);
239*600f14f4SXin Li
240*600f14f4SXin Li if(0 != *tempfile) {
241*600f14f4SXin Li (void)fclose(*tempfile);
242*600f14f4SXin Li *tempfile = 0;
243*600f14f4SXin Li }
244*600f14f4SXin Li
245*600f14f4SXin Li #if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
246*600f14f4SXin Li /* on some flavors of windows, flac_rename() will fail if the destination already exists */
247*600f14f4SXin Li if(flac_unlink(filename) < 0) {
248*600f14f4SXin Li cleanup_tempfile_(tempfile, tempfilename);
249*600f14f4SXin Li return false;
250*600f14f4SXin Li }
251*600f14f4SXin Li #endif
252*600f14f4SXin Li
253*600f14f4SXin Li if(0 != flac_rename(*tempfilename, filename)) {
254*600f14f4SXin Li cleanup_tempfile_(tempfile, tempfilename);
255*600f14f4SXin Li return false;
256*600f14f4SXin Li }
257*600f14f4SXin Li
258*600f14f4SXin Li cleanup_tempfile_(tempfile, tempfilename);
259*600f14f4SXin Li
260*600f14f4SXin Li return true;
261*600f14f4SXin Li }
262*600f14f4SXin Li
get_file_stats_(const char * filename,struct flac_stat_s * stats)263*600f14f4SXin Li bool get_file_stats_(const char *filename, struct flac_stat_s *stats)
264*600f14f4SXin Li {
265*600f14f4SXin Li FLAC__ASSERT(0 != filename);
266*600f14f4SXin Li FLAC__ASSERT(0 != stats);
267*600f14f4SXin Li return (0 == flac_stat(filename, stats));
268*600f14f4SXin Li }
269*600f14f4SXin Li
set_file_stats_(const char * filename,struct flac_stat_s * stats)270*600f14f4SXin Li void set_file_stats_(const char *filename, struct flac_stat_s *stats)
271*600f14f4SXin Li {
272*600f14f4SXin Li FLAC__ASSERT(0 != filename);
273*600f14f4SXin Li FLAC__ASSERT(0 != stats);
274*600f14f4SXin Li
275*600f14f4SXin Li #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) && !defined(_WIN32)
276*600f14f4SXin Li struct timespec srctime[2] = {};
277*600f14f4SXin Li srctime[0].tv_sec = stats->st_atime;
278*600f14f4SXin Li srctime[1].tv_sec = stats->st_mtime;
279*600f14f4SXin Li #else
280*600f14f4SXin Li struct utimbuf srctime;
281*600f14f4SXin Li srctime.actime = stats->st_atime;
282*600f14f4SXin Li srctime.modtime = stats->st_mtime;
283*600f14f4SXin Li #endif
284*600f14f4SXin Li (void)flac_chmod(filename, stats->st_mode);
285*600f14f4SXin Li (void)flac_utime(filename, &srctime);
286*600f14f4SXin Li #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
287*600f14f4SXin Li FLAC_CHECK_RETURN(chown(filename, stats->st_uid, (gid_t)(-1)));
288*600f14f4SXin Li FLAC_CHECK_RETURN(chown(filename, (uid_t)(-1), stats->st_gid));
289*600f14f4SXin Li #endif
290*600f14f4SXin Li }
291*600f14f4SXin Li
292*600f14f4SXin Li #ifdef FLAC__VALGRIND_TESTING
chain_write_cb_(const void * ptr,size_t size,size_t nmemb,::FLAC__IOHandle handle)293*600f14f4SXin Li static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, ::FLAC__IOHandle handle)
294*600f14f4SXin Li {
295*600f14f4SXin Li FILE *stream = (FILE*)handle;
296*600f14f4SXin Li size_t ret = fwrite(ptr, size, nmemb, stream);
297*600f14f4SXin Li if(!ferror(stream))
298*600f14f4SXin Li fflush(stream);
299*600f14f4SXin Li return ret;
300*600f14f4SXin Li }
301*600f14f4SXin Li #endif
302*600f14f4SXin Li
chain_seek_cb_(::FLAC__IOHandle handle,FLAC__int64 offset,int whence)303*600f14f4SXin Li static int chain_seek_cb_(::FLAC__IOHandle handle, FLAC__int64 offset, int whence)
304*600f14f4SXin Li {
305*600f14f4SXin Li FLAC__off_t o = (FLAC__off_t)offset;
306*600f14f4SXin Li FLAC__ASSERT(offset == o);
307*600f14f4SXin Li return fseeko((FILE*)handle, o, whence);
308*600f14f4SXin Li }
309*600f14f4SXin Li
chain_tell_cb_(::FLAC__IOHandle handle)310*600f14f4SXin Li static FLAC__int64 chain_tell_cb_(::FLAC__IOHandle handle)
311*600f14f4SXin Li {
312*600f14f4SXin Li return ftello((FILE*)handle);
313*600f14f4SXin Li }
314*600f14f4SXin Li
chain_eof_cb_(::FLAC__IOHandle handle)315*600f14f4SXin Li static int chain_eof_cb_(::FLAC__IOHandle handle)
316*600f14f4SXin Li {
317*600f14f4SXin Li return feof((FILE*)handle);
318*600f14f4SXin Li }
319*600f14f4SXin Li
write_chain_(FLAC::Metadata::Chain & chain,bool use_padding,bool preserve_file_stats,bool filename_based,const char * filename)320*600f14f4SXin Li static bool write_chain_(FLAC::Metadata::Chain &chain, bool use_padding, bool preserve_file_stats, bool filename_based, const char *filename)
321*600f14f4SXin Li {
322*600f14f4SXin Li if(filename_based)
323*600f14f4SXin Li return chain.write(use_padding, preserve_file_stats);
324*600f14f4SXin Li else {
325*600f14f4SXin Li ::FLAC__IOCallbacks callbacks;
326*600f14f4SXin Li
327*600f14f4SXin Li memset(&callbacks, 0, sizeof(callbacks));
328*600f14f4SXin Li callbacks.read = (::FLAC__IOCallback_Read)fread;
329*600f14f4SXin Li #ifdef FLAC__VALGRIND_TESTING
330*600f14f4SXin Li callbacks.write = chain_write_cb_;
331*600f14f4SXin Li #else
332*600f14f4SXin Li callbacks.write = (::FLAC__IOCallback_Write)fwrite;
333*600f14f4SXin Li #endif
334*600f14f4SXin Li callbacks.seek = chain_seek_cb_;
335*600f14f4SXin Li callbacks.eof = chain_eof_cb_;
336*600f14f4SXin Li
337*600f14f4SXin Li if(chain.check_if_tempfile_needed(use_padding)) {
338*600f14f4SXin Li struct flac_stat_s stats;
339*600f14f4SXin Li FILE *file, *tempfile;
340*600f14f4SXin Li char *tempfilename;
341*600f14f4SXin Li if(preserve_file_stats) {
342*600f14f4SXin Li if(!get_file_stats_(filename, &stats))
343*600f14f4SXin Li return false;
344*600f14f4SXin Li }
345*600f14f4SXin Li if(0 == (file = flac_fopen(filename, "rb")))
346*600f14f4SXin Li return false; /*@@@@ chain status still says OK though */
347*600f14f4SXin Li if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
348*600f14f4SXin Li fclose(file);
349*600f14f4SXin Li cleanup_tempfile_(&tempfile, &tempfilename);
350*600f14f4SXin Li return false; /*@@@@ chain status still says OK though */
351*600f14f4SXin Li }
352*600f14f4SXin Li if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks, (::FLAC__IOHandle)tempfile, callbacks)) {
353*600f14f4SXin Li fclose(file);
354*600f14f4SXin Li fclose(tempfile);
355*600f14f4SXin Li return false;
356*600f14f4SXin Li }
357*600f14f4SXin Li fclose(file);
358*600f14f4SXin Li fclose(tempfile);
359*600f14f4SXin Li file = tempfile = 0;
360*600f14f4SXin Li if(!transport_tempfile_(filename, &tempfile, &tempfilename))
361*600f14f4SXin Li return false;
362*600f14f4SXin Li if(preserve_file_stats)
363*600f14f4SXin Li set_file_stats_(filename, &stats);
364*600f14f4SXin Li }
365*600f14f4SXin Li else {
366*600f14f4SXin Li FILE *file = flac_fopen(filename, "r+b");
367*600f14f4SXin Li if(0 == file)
368*600f14f4SXin Li return false; /*@@@@ chain status still says OK though */
369*600f14f4SXin Li if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks)) {
370*600f14f4SXin Li fclose(file);
371*600f14f4SXin Li return false;
372*600f14f4SXin Li }
373*600f14f4SXin Li fclose(file);
374*600f14f4SXin Li }
375*600f14f4SXin Li }
376*600f14f4SXin Li
377*600f14f4SXin Li return true;
378*600f14f4SXin Li }
379*600f14f4SXin Li
read_chain_(FLAC::Metadata::Chain & chain,const char * filename,bool filename_based,bool is_ogg)380*600f14f4SXin Li static bool read_chain_(FLAC::Metadata::Chain &chain, const char *filename, bool filename_based, bool is_ogg)
381*600f14f4SXin Li {
382*600f14f4SXin Li if(filename_based)
383*600f14f4SXin Li return chain.read(filename, is_ogg);
384*600f14f4SXin Li else {
385*600f14f4SXin Li ::FLAC__IOCallbacks callbacks;
386*600f14f4SXin Li
387*600f14f4SXin Li memset(&callbacks, 0, sizeof(callbacks));
388*600f14f4SXin Li callbacks.read = (::FLAC__IOCallback_Read)fread;
389*600f14f4SXin Li callbacks.seek = chain_seek_cb_;
390*600f14f4SXin Li callbacks.tell = chain_tell_cb_;
391*600f14f4SXin Li
392*600f14f4SXin Li {
393*600f14f4SXin Li bool ret;
394*600f14f4SXin Li FILE *file = flac_fopen(filename, "rb");
395*600f14f4SXin Li if(0 == file)
396*600f14f4SXin Li return false; /*@@@@ chain status still says OK though */
397*600f14f4SXin Li ret = chain.read((::FLAC__IOHandle)file, callbacks, is_ogg);
398*600f14f4SXin Li fclose(file);
399*600f14f4SXin Li return ret;
400*600f14f4SXin Li }
401*600f14f4SXin Li }
402*600f14f4SXin Li }
403*600f14f4SXin Li
404*600f14f4SXin Li /* function for comparing our metadata to a FLAC::Metadata::Chain */
405*600f14f4SXin Li
compare_chain_(FLAC::Metadata::Chain & chain,uint32_t current_position,FLAC::Metadata::Prototype * current_block)406*600f14f4SXin Li static bool compare_chain_(FLAC::Metadata::Chain &chain, uint32_t current_position, FLAC::Metadata::Prototype *current_block)
407*600f14f4SXin Li {
408*600f14f4SXin Li uint32_t i;
409*600f14f4SXin Li FLAC::Metadata::Iterator iterator;
410*600f14f4SXin Li bool next_ok = true;
411*600f14f4SXin Li
412*600f14f4SXin Li printf("\tcomparing chain... ");
413*600f14f4SXin Li fflush(stdout);
414*600f14f4SXin Li
415*600f14f4SXin Li if(!iterator.is_valid())
416*600f14f4SXin Li return die_("allocating memory for iterator");
417*600f14f4SXin Li
418*600f14f4SXin Li iterator.init(chain);
419*600f14f4SXin Li
420*600f14f4SXin Li i = 0;
421*600f14f4SXin Li do {
422*600f14f4SXin Li FLAC::Metadata::Prototype *block;
423*600f14f4SXin Li
424*600f14f4SXin Li printf("%u... ", i);
425*600f14f4SXin Li fflush(stdout);
426*600f14f4SXin Li
427*600f14f4SXin Li if(0 == (block = iterator.get_block()))
428*600f14f4SXin Li return die_("getting block from iterator");
429*600f14f4SXin Li
430*600f14f4SXin Li if(*block != *our_metadata_.blocks[i])
431*600f14f4SXin Li return die_("metadata block mismatch");
432*600f14f4SXin Li
433*600f14f4SXin Li delete block;
434*600f14f4SXin Li i++;
435*600f14f4SXin Li next_ok = iterator.next();
436*600f14f4SXin Li } while(i < our_metadata_.num_blocks && next_ok);
437*600f14f4SXin Li
438*600f14f4SXin Li if(next_ok)
439*600f14f4SXin Li return die_("chain has more blocks than expected");
440*600f14f4SXin Li
441*600f14f4SXin Li if(i < our_metadata_.num_blocks)
442*600f14f4SXin Li return die_("short block count in chain");
443*600f14f4SXin Li
444*600f14f4SXin Li if(0 != current_block) {
445*600f14f4SXin Li printf("CURRENT_POSITION... ");
446*600f14f4SXin Li fflush(stdout);
447*600f14f4SXin Li
448*600f14f4SXin Li if(*current_block != *our_metadata_.blocks[current_position])
449*600f14f4SXin Li return die_("metadata block mismatch");
450*600f14f4SXin Li }
451*600f14f4SXin Li
452*600f14f4SXin Li printf("PASSED\n");
453*600f14f4SXin Li
454*600f14f4SXin Li return true;
455*600f14f4SXin Li }
456*600f14f4SXin Li
write_callback(const::FLAC__Frame * frame,const FLAC__int32 * const buffer[])457*600f14f4SXin Li ::FLAC__StreamDecoderWriteStatus OurFileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
458*600f14f4SXin Li {
459*600f14f4SXin Li (void)buffer;
460*600f14f4SXin Li
461*600f14f4SXin Li if(
462*600f14f4SXin Li (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
463*600f14f4SXin Li (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
464*600f14f4SXin Li ) {
465*600f14f4SXin Li printf("content... ");
466*600f14f4SXin Li fflush(stdout);
467*600f14f4SXin Li }
468*600f14f4SXin Li
469*600f14f4SXin Li return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
470*600f14f4SXin Li }
471*600f14f4SXin Li
metadata_callback(const::FLAC__StreamMetadata * metadata)472*600f14f4SXin Li void OurFileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
473*600f14f4SXin Li {
474*600f14f4SXin Li /* don't bother checking if we've already hit an error */
475*600f14f4SXin Li if(error_occurred_)
476*600f14f4SXin Li return;
477*600f14f4SXin Li
478*600f14f4SXin Li printf("%u... ", mc_our_block_number_);
479*600f14f4SXin Li fflush(stdout);
480*600f14f4SXin Li
481*600f14f4SXin Li if(!ignore_metadata_) {
482*600f14f4SXin Li if(mc_our_block_number_ >= our_metadata_.num_blocks) {
483*600f14f4SXin Li (void)die_("got more metadata blocks than expected");
484*600f14f4SXin Li error_occurred_ = true;
485*600f14f4SXin Li }
486*600f14f4SXin Li else {
487*600f14f4SXin Li if(*our_metadata_.blocks[mc_our_block_number_] != metadata) {
488*600f14f4SXin Li (void)die_("metadata block mismatch");
489*600f14f4SXin Li error_occurred_ = true;
490*600f14f4SXin Li }
491*600f14f4SXin Li }
492*600f14f4SXin Li }
493*600f14f4SXin Li
494*600f14f4SXin Li mc_our_block_number_++;
495*600f14f4SXin Li }
496*600f14f4SXin Li
error_callback(::FLAC__StreamDecoderErrorStatus status)497*600f14f4SXin Li void OurFileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
498*600f14f4SXin Li {
499*600f14f4SXin Li error_occurred_ = true;
500*600f14f4SXin Li printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (uint32_t)status);
501*600f14f4SXin Li }
502*600f14f4SXin Li
generate_file_(bool include_extras,bool is_ogg)503*600f14f4SXin Li static bool generate_file_(bool include_extras, bool is_ogg)
504*600f14f4SXin Li {
505*600f14f4SXin Li ::FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
506*600f14f4SXin Li ::FLAC__StreamMetadata *metadata[4];
507*600f14f4SXin Li uint32_t i = 0, n = 0;
508*600f14f4SXin Li
509*600f14f4SXin Li printf("generating %sFLAC file for test\n", is_ogg? "Ogg " : "");
510*600f14f4SXin Li
511*600f14f4SXin Li while(our_metadata_.num_blocks > 0)
512*600f14f4SXin Li delete_from_our_metadata_(0);
513*600f14f4SXin Li
514*600f14f4SXin Li streaminfo.is_last = false;
515*600f14f4SXin Li streaminfo.type = ::FLAC__METADATA_TYPE_STREAMINFO;
516*600f14f4SXin Li streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
517*600f14f4SXin Li streaminfo.data.stream_info.min_blocksize = 576;
518*600f14f4SXin Li streaminfo.data.stream_info.max_blocksize = 576;
519*600f14f4SXin Li streaminfo.data.stream_info.min_framesize = 0;
520*600f14f4SXin Li streaminfo.data.stream_info.max_framesize = 0;
521*600f14f4SXin Li streaminfo.data.stream_info.sample_rate = 44100;
522*600f14f4SXin Li streaminfo.data.stream_info.channels = 1;
523*600f14f4SXin Li streaminfo.data.stream_info.bits_per_sample = 8;
524*600f14f4SXin Li streaminfo.data.stream_info.total_samples = 0;
525*600f14f4SXin Li memset(streaminfo.data.stream_info.md5sum, 0, 16);
526*600f14f4SXin Li
527*600f14f4SXin Li {
528*600f14f4SXin Li const uint32_t vendor_string_length = (uint32_t)strlen(FLAC__VENDOR_STRING);
529*600f14f4SXin Li vorbiscomment.is_last = false;
530*600f14f4SXin Li vorbiscomment.type = ::FLAC__METADATA_TYPE_VORBIS_COMMENT;
531*600f14f4SXin Li vorbiscomment.length = (4 + vendor_string_length) + 4;
532*600f14f4SXin Li vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
533*600f14f4SXin Li vorbiscomment.data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
534*600f14f4SXin Li memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
535*600f14f4SXin Li vorbiscomment.data.vorbis_comment.num_comments = 0;
536*600f14f4SXin Li vorbiscomment.data.vorbis_comment.comments = 0;
537*600f14f4SXin Li }
538*600f14f4SXin Li
539*600f14f4SXin Li {
540*600f14f4SXin Li if (0 == (cuesheet = ::FLAC__metadata_object_new(::FLAC__METADATA_TYPE_CUESHEET)))
541*600f14f4SXin Li return die_("priming our metadata");
542*600f14f4SXin Li cuesheet->is_last = false;
543*600f14f4SXin Li safe_strncpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN", sizeof(cuesheet->data.cue_sheet.media_catalog_number));
544*600f14f4SXin Li cuesheet->data.cue_sheet.lead_in = 123;
545*600f14f4SXin Li cuesheet->data.cue_sheet.is_cd = false;
546*600f14f4SXin Li if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))
547*600f14f4SXin Li return die_("priming our metadata");
548*600f14f4SXin Li cuesheet->data.cue_sheet.tracks[0].number = 1;
549*600f14f4SXin Li if (!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, 0, 0))
550*600f14f4SXin Li return die_("priming our metadata");
551*600f14f4SXin Li }
552*600f14f4SXin Li
553*600f14f4SXin Li {
554*600f14f4SXin Li picture.is_last = false;
555*600f14f4SXin Li picture.type = ::FLAC__METADATA_TYPE_PICTURE;
556*600f14f4SXin Li picture.length =
557*600f14f4SXin Li (
558*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
559*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
560*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
561*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
562*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
563*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
564*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
565*600f14f4SXin Li FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
566*600f14f4SXin Li ) / 8
567*600f14f4SXin Li ;
568*600f14f4SXin Li picture.data.picture.type = ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
569*600f14f4SXin Li picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
570*600f14f4SXin Li picture.length += strlen(picture.data.picture.mime_type);
571*600f14f4SXin Li picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
572*600f14f4SXin Li picture.length += strlen((const char *)picture.data.picture.description);
573*600f14f4SXin Li picture.data.picture.width = 300;
574*600f14f4SXin Li picture.data.picture.height = 300;
575*600f14f4SXin Li picture.data.picture.depth = 24;
576*600f14f4SXin Li picture.data.picture.colors = 0;
577*600f14f4SXin Li picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
578*600f14f4SXin Li picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
579*600f14f4SXin Li picture.length += picture.data.picture.data_length;
580*600f14f4SXin Li }
581*600f14f4SXin Li
582*600f14f4SXin Li padding.is_last = true;
583*600f14f4SXin Li padding.type = ::FLAC__METADATA_TYPE_PADDING;
584*600f14f4SXin Li padding.length = 1234;
585*600f14f4SXin Li
586*600f14f4SXin Li metadata[n++] = &vorbiscomment;
587*600f14f4SXin Li if(include_extras) {
588*600f14f4SXin Li metadata[n++] = cuesheet;
589*600f14f4SXin Li metadata[n++] = &picture;
590*600f14f4SXin Li }
591*600f14f4SXin Li metadata[n++] = &padding;
592*600f14f4SXin Li
593*600f14f4SXin Li FLAC::Metadata::StreamInfo s(&streaminfo);
594*600f14f4SXin Li FLAC::Metadata::VorbisComment v(&vorbiscomment);
595*600f14f4SXin Li FLAC::Metadata::CueSheet c(cuesheet, /*copy=*/false);
596*600f14f4SXin Li FLAC::Metadata::Picture pi(&picture);
597*600f14f4SXin Li FLAC::Metadata::Padding p(&padding);
598*600f14f4SXin Li if(
599*600f14f4SXin Li !insert_to_our_metadata_(&s, i++, /*copy=*/true) ||
600*600f14f4SXin Li !insert_to_our_metadata_(&v, i++, /*copy=*/true) ||
601*600f14f4SXin Li (include_extras && !insert_to_our_metadata_(&c, i++, /*copy=*/true)) ||
602*600f14f4SXin Li (include_extras && !insert_to_our_metadata_(&pi, i++, /*copy=*/true)) ||
603*600f14f4SXin Li !insert_to_our_metadata_(&p, i++, /*copy=*/true)
604*600f14f4SXin Li )
605*600f14f4SXin Li return die_("priming our metadata");
606*600f14f4SXin Li
607*600f14f4SXin Li if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), 0, 512 * 1024, &streaminfo, metadata, n))
608*600f14f4SXin Li return die_("creating the encoded file");
609*600f14f4SXin Li
610*600f14f4SXin Li free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
611*600f14f4SXin Li free(picture.data.picture.mime_type);
612*600f14f4SXin Li free(picture.data.picture.description);
613*600f14f4SXin Li free(picture.data.picture.data);
614*600f14f4SXin Li
615*600f14f4SXin Li return true;
616*600f14f4SXin Li }
617*600f14f4SXin Li
test_file_(bool is_ogg,bool ignore_metadata)618*600f14f4SXin Li static bool test_file_(bool is_ogg, bool ignore_metadata)
619*600f14f4SXin Li {
620*600f14f4SXin Li const char *filename = flacfilename(is_ogg);
621*600f14f4SXin Li OurFileDecoder decoder(ignore_metadata);
622*600f14f4SXin Li
623*600f14f4SXin Li mc_our_block_number_ = 0;
624*600f14f4SXin Li decoder.error_occurred_ = false;
625*600f14f4SXin Li
626*600f14f4SXin Li printf("\ttesting '%s'... ", filename);
627*600f14f4SXin Li fflush(stdout);
628*600f14f4SXin Li
629*600f14f4SXin Li if(!decoder.is_valid())
630*600f14f4SXin Li return die_("couldn't allocate decoder instance");
631*600f14f4SXin Li
632*600f14f4SXin Li decoder.set_md5_checking(true);
633*600f14f4SXin Li decoder.set_metadata_respond_all();
634*600f14f4SXin Li if((is_ogg? decoder.init_ogg(filename) : decoder.init(filename)) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK) {
635*600f14f4SXin Li (void)decoder.finish();
636*600f14f4SXin Li return die_("initializing decoder\n");
637*600f14f4SXin Li }
638*600f14f4SXin Li if(!decoder.process_until_end_of_stream()) {
639*600f14f4SXin Li (void)decoder.finish();
640*600f14f4SXin Li return die_("decoding file\n");
641*600f14f4SXin Li }
642*600f14f4SXin Li
643*600f14f4SXin Li (void)decoder.finish();
644*600f14f4SXin Li
645*600f14f4SXin Li if(decoder.error_occurred_)
646*600f14f4SXin Li return false;
647*600f14f4SXin Li
648*600f14f4SXin Li if(mc_our_block_number_ != our_metadata_.num_blocks)
649*600f14f4SXin Li return die_("short metadata block count");
650*600f14f4SXin Li
651*600f14f4SXin Li printf("PASSED\n");
652*600f14f4SXin Li return true;
653*600f14f4SXin Li }
654*600f14f4SXin Li
change_stats_(const char * filename,bool read_only)655*600f14f4SXin Li static bool change_stats_(const char *filename, bool read_only)
656*600f14f4SXin Li {
657*600f14f4SXin Li if(!grabbag__file_change_stats(filename, read_only))
658*600f14f4SXin Li return die_("during grabbag__file_change_stats()");
659*600f14f4SXin Li
660*600f14f4SXin Li return true;
661*600f14f4SXin Li }
662*600f14f4SXin Li
remove_file_(const char * filename)663*600f14f4SXin Li static bool remove_file_(const char *filename)
664*600f14f4SXin Li {
665*600f14f4SXin Li while(our_metadata_.num_blocks > 0)
666*600f14f4SXin Li delete_from_our_metadata_(0);
667*600f14f4SXin Li
668*600f14f4SXin Li if(!grabbag__file_remove_file(filename))
669*600f14f4SXin Li return die_("removing file");
670*600f14f4SXin Li
671*600f14f4SXin Li return true;
672*600f14f4SXin Li }
673*600f14f4SXin Li
test_level_0_()674*600f14f4SXin Li static bool test_level_0_()
675*600f14f4SXin Li {
676*600f14f4SXin Li FLAC::Metadata::StreamInfo streaminfo;
677*600f14f4SXin Li
678*600f14f4SXin Li printf("\n\n++++++ testing level 0 interface\n");
679*600f14f4SXin Li
680*600f14f4SXin Li if(!generate_file_(/*include_extras=*/true, /*is_ogg=*/false))
681*600f14f4SXin Li return false;
682*600f14f4SXin Li
683*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/true))
684*600f14f4SXin Li return false;
685*600f14f4SXin Li
686*600f14f4SXin Li printf("testing FLAC::Metadata::get_streaminfo()... ");
687*600f14f4SXin Li
688*600f14f4SXin Li if(!FLAC::Metadata::get_streaminfo(flacfilename(/*is_ogg=*/false), streaminfo))
689*600f14f4SXin Li return die_("during FLAC::Metadata::get_streaminfo()");
690*600f14f4SXin Li
691*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
692*600f14f4SXin Li if(streaminfo.get_channels() != 1)
693*600f14f4SXin Li return die_("mismatch in streaminfo.get_channels()");
694*600f14f4SXin Li if(streaminfo.get_bits_per_sample() != 8)
695*600f14f4SXin Li return die_("mismatch in streaminfo.get_bits_per_sample()");
696*600f14f4SXin Li if(streaminfo.get_sample_rate() != 44100)
697*600f14f4SXin Li return die_("mismatch in streaminfo.get_sample_rate()");
698*600f14f4SXin Li if(streaminfo.get_min_blocksize() != 576)
699*600f14f4SXin Li return die_("mismatch in streaminfo.get_min_blocksize()");
700*600f14f4SXin Li if(streaminfo.get_max_blocksize() != 576)
701*600f14f4SXin Li return die_("mismatch in streaminfo.get_max_blocksize()");
702*600f14f4SXin Li
703*600f14f4SXin Li printf("OK\n");
704*600f14f4SXin Li
705*600f14f4SXin Li {
706*600f14f4SXin Li printf("testing FLAC::Metadata::get_tags(VorbisComment *&)... ");
707*600f14f4SXin Li
708*600f14f4SXin Li FLAC::Metadata::VorbisComment *tags = 0;
709*600f14f4SXin Li
710*600f14f4SXin Li if(!FLAC::Metadata::get_tags(flacfilename(/*is_ogg=*/false), tags))
711*600f14f4SXin Li return die_("during FLAC::Metadata::get_tags()");
712*600f14f4SXin Li
713*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
714*600f14f4SXin Li if(tags->get_num_comments() != 0)
715*600f14f4SXin Li return die_("mismatch in tags->get_num_comments()");
716*600f14f4SXin Li
717*600f14f4SXin Li printf("OK\n");
718*600f14f4SXin Li
719*600f14f4SXin Li delete tags;
720*600f14f4SXin Li }
721*600f14f4SXin Li
722*600f14f4SXin Li {
723*600f14f4SXin Li printf("testing FLAC::Metadata::get_tags(VorbisComment &)... ");
724*600f14f4SXin Li
725*600f14f4SXin Li FLAC::Metadata::VorbisComment tags;
726*600f14f4SXin Li
727*600f14f4SXin Li if(!FLAC::Metadata::get_tags(flacfilename(/*is_ogg=*/false), tags))
728*600f14f4SXin Li return die_("during FLAC::Metadata::get_tags()");
729*600f14f4SXin Li
730*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
731*600f14f4SXin Li if(tags.get_num_comments() != 0)
732*600f14f4SXin Li return die_("mismatch in tags.get_num_comments()");
733*600f14f4SXin Li
734*600f14f4SXin Li printf("OK\n");
735*600f14f4SXin Li }
736*600f14f4SXin Li
737*600f14f4SXin Li {
738*600f14f4SXin Li printf("testing FLAC::Metadata::get_cuesheet(CueSheet *&)... ");
739*600f14f4SXin Li
740*600f14f4SXin Li FLAC::Metadata::CueSheet *cuesheet = 0;
741*600f14f4SXin Li
742*600f14f4SXin Li if(!FLAC::Metadata::get_cuesheet(flacfilename(/*is_ogg=*/false), cuesheet))
743*600f14f4SXin Li return die_("during FLAC::Metadata::get_cuesheet()");
744*600f14f4SXin Li
745*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
746*600f14f4SXin Li if(cuesheet->get_lead_in() != 123)
747*600f14f4SXin Li return die_("mismatch in cuesheet->get_lead_in()");
748*600f14f4SXin Li
749*600f14f4SXin Li printf("OK\n");
750*600f14f4SXin Li
751*600f14f4SXin Li delete cuesheet;
752*600f14f4SXin Li }
753*600f14f4SXin Li
754*600f14f4SXin Li {
755*600f14f4SXin Li printf("testing FLAC::Metadata::get_cuesheet(CueSheet &)... ");
756*600f14f4SXin Li
757*600f14f4SXin Li FLAC::Metadata::CueSheet cuesheet;
758*600f14f4SXin Li
759*600f14f4SXin Li if(!FLAC::Metadata::get_cuesheet(flacfilename(/*is_ogg=*/false), cuesheet))
760*600f14f4SXin Li return die_("during FLAC::Metadata::get_cuesheet()");
761*600f14f4SXin Li
762*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
763*600f14f4SXin Li if(cuesheet.get_lead_in() != 123)
764*600f14f4SXin Li return die_("mismatch in cuesheet.get_lead_in()");
765*600f14f4SXin Li
766*600f14f4SXin Li printf("OK\n");
767*600f14f4SXin Li }
768*600f14f4SXin Li
769*600f14f4SXin Li {
770*600f14f4SXin Li printf("testing FLAC::Metadata::get_picture(Picture *&)... ");
771*600f14f4SXin Li
772*600f14f4SXin Li FLAC::Metadata::Picture *picture = 0;
773*600f14f4SXin Li
774*600f14f4SXin Li if(!FLAC::Metadata::get_picture(flacfilename(/*is_ogg=*/false), picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(uint32_t)(-1), /*max_height=*/(uint32_t)(-1), /*max_depth=*/(uint32_t)(-1), /*max_colors=*/(uint32_t)(-1)))
775*600f14f4SXin Li return die_("during FLAC::Metadata::get_picture()");
776*600f14f4SXin Li
777*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
778*600f14f4SXin Li if(picture->get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
779*600f14f4SXin Li return die_("mismatch in picture->get_type ()");
780*600f14f4SXin Li
781*600f14f4SXin Li printf("OK\n");
782*600f14f4SXin Li
783*600f14f4SXin Li delete picture;
784*600f14f4SXin Li }
785*600f14f4SXin Li
786*600f14f4SXin Li {
787*600f14f4SXin Li printf("testing FLAC::Metadata::get_picture(Picture &)... ");
788*600f14f4SXin Li
789*600f14f4SXin Li FLAC::Metadata::Picture picture;
790*600f14f4SXin Li
791*600f14f4SXin Li if(!FLAC::Metadata::get_picture(flacfilename(/*is_ogg=*/false), picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(uint32_t)(-1), /*max_height=*/(uint32_t)(-1), /*max_depth=*/(uint32_t)(-1), /*max_colors=*/(uint32_t)(-1)))
792*600f14f4SXin Li return die_("during FLAC::Metadata::get_picture()");
793*600f14f4SXin Li
794*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
795*600f14f4SXin Li if(picture.get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
796*600f14f4SXin Li return die_("mismatch in picture->get_type ()");
797*600f14f4SXin Li
798*600f14f4SXin Li printf("OK\n");
799*600f14f4SXin Li }
800*600f14f4SXin Li
801*600f14f4SXin Li if(!remove_file_(flacfilename(/*is_ogg=*/false)))
802*600f14f4SXin Li return false;
803*600f14f4SXin Li
804*600f14f4SXin Li return true;
805*600f14f4SXin Li }
806*600f14f4SXin Li
test_level_1_()807*600f14f4SXin Li static bool test_level_1_()
808*600f14f4SXin Li {
809*600f14f4SXin Li FLAC::Metadata::Prototype *block;
810*600f14f4SXin Li FLAC::Metadata::StreamInfo *streaminfo;
811*600f14f4SXin Li FLAC::Metadata::Padding *padding;
812*600f14f4SXin Li FLAC::Metadata::Application *app;
813*600f14f4SXin Li FLAC__byte data[1000];
814*600f14f4SXin Li uint32_t our_current_position = 0;
815*600f14f4SXin Li
816*600f14f4SXin Li // initialize 'data' to avoid Valgrind errors
817*600f14f4SXin Li memset(data, 0, sizeof(data));
818*600f14f4SXin Li
819*600f14f4SXin Li printf("\n\n++++++ testing level 1 interface\n");
820*600f14f4SXin Li
821*600f14f4SXin Li /************************************************************/
822*600f14f4SXin Li {
823*600f14f4SXin Li printf("simple iterator on read-only file\n");
824*600f14f4SXin Li
825*600f14f4SXin Li if(!generate_file_(/*include_extras=*/false, /*is_ogg=*/false))
826*600f14f4SXin Li return false;
827*600f14f4SXin Li
828*600f14f4SXin Li if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read_only=*/true))
829*600f14f4SXin Li return false;
830*600f14f4SXin Li
831*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/true))
832*600f14f4SXin Li return false;
833*600f14f4SXin Li
834*600f14f4SXin Li FLAC::Metadata::SimpleIterator iterator;
835*600f14f4SXin Li
836*600f14f4SXin Li if(!iterator.is_valid())
837*600f14f4SXin Li return die_("iterator.is_valid() returned false");
838*600f14f4SXin Li
839*600f14f4SXin Li if(!iterator.init(flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false))
840*600f14f4SXin Li return die_("iterator.init() returned false");
841*600f14f4SXin Li
842*600f14f4SXin Li printf("is writable = %u\n", (uint32_t)iterator.is_writable());
843*600f14f4SXin Li if(iterator.is_writable())
844*600f14f4SXin Li return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?\n");
845*600f14f4SXin Li
846*600f14f4SXin Li printf("iterate forwards\n");
847*600f14f4SXin Li
848*600f14f4SXin Li if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
849*600f14f4SXin Li return die_("expected STREAMINFO type from iterator.get_block_type()");
850*600f14f4SXin Li if(0 == (block = iterator.get_block()))
851*600f14f4SXin Li return die_("getting block 0");
852*600f14f4SXin Li if(block->get_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
853*600f14f4SXin Li return die_("expected STREAMINFO type");
854*600f14f4SXin Li if(block->get_is_last())
855*600f14f4SXin Li return die_("expected is_last to be false");
856*600f14f4SXin Li if(block->get_length() != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
857*600f14f4SXin Li return die_("bad STREAMINFO length");
858*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
859*600f14f4SXin Li streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
860*600f14f4SXin Li FLAC__ASSERT(0 != streaminfo);
861*600f14f4SXin Li if(streaminfo->get_channels() != 1)
862*600f14f4SXin Li return die_("mismatch in channels");
863*600f14f4SXin Li if(streaminfo->get_bits_per_sample() != 8)
864*600f14f4SXin Li return die_("mismatch in bits_per_sample");
865*600f14f4SXin Li if(streaminfo->get_sample_rate() != 44100)
866*600f14f4SXin Li return die_("mismatch in sample_rate");
867*600f14f4SXin Li if(streaminfo->get_min_blocksize() != 576)
868*600f14f4SXin Li return die_("mismatch in min_blocksize");
869*600f14f4SXin Li if(streaminfo->get_max_blocksize() != 576)
870*600f14f4SXin Li return die_("mismatch in max_blocksize");
871*600f14f4SXin Li // we will delete streaminfo a little later when we're really done with it...
872*600f14f4SXin Li
873*600f14f4SXin Li if(!iterator.next())
874*600f14f4SXin Li return die_("forward iterator ended early");
875*600f14f4SXin Li our_current_position++;
876*600f14f4SXin Li
877*600f14f4SXin Li if(!iterator.next())
878*600f14f4SXin Li return die_("forward iterator ended early");
879*600f14f4SXin Li our_current_position++;
880*600f14f4SXin Li
881*600f14f4SXin Li if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_PADDING)
882*600f14f4SXin Li return die_("expected PADDING type from iterator.get_block_type()");
883*600f14f4SXin Li if(0 == (block = iterator.get_block()))
884*600f14f4SXin Li return die_("getting block 1");
885*600f14f4SXin Li if(block->get_type() != ::FLAC__METADATA_TYPE_PADDING)
886*600f14f4SXin Li return die_("expected PADDING type");
887*600f14f4SXin Li if(!block->get_is_last())
888*600f14f4SXin Li return die_("expected is_last to be true");
889*600f14f4SXin Li /* check to see if some basic data matches (c.f. generate_file_()) */
890*600f14f4SXin Li if(block->get_length() != 1234)
891*600f14f4SXin Li return die_("bad PADDING length");
892*600f14f4SXin Li delete block;
893*600f14f4SXin Li
894*600f14f4SXin Li if(iterator.next())
895*600f14f4SXin Li return die_("forward iterator returned true but should have returned false");
896*600f14f4SXin Li
897*600f14f4SXin Li printf("iterate backwards\n");
898*600f14f4SXin Li if(!iterator.prev())
899*600f14f4SXin Li return die_("reverse iterator ended early");
900*600f14f4SXin Li if(!iterator.prev())
901*600f14f4SXin Li return die_("reverse iterator ended early");
902*600f14f4SXin Li if(iterator.prev())
903*600f14f4SXin Li return die_("reverse iterator returned true but should have returned false");
904*600f14f4SXin Li
905*600f14f4SXin Li printf("testing iterator.set_block() on read-only file...\n");
906*600f14f4SXin Li
907*600f14f4SXin Li if(!iterator.set_block(streaminfo, false))
908*600f14f4SXin Li printf("PASSED. iterator.set_block() returned false like it should\n");
909*600f14f4SXin Li else
910*600f14f4SXin Li return die_("iterator.set_block() returned true but shouldn't have");
911*600f14f4SXin Li delete streaminfo;
912*600f14f4SXin Li }
913*600f14f4SXin Li
914*600f14f4SXin Li /************************************************************/
915*600f14f4SXin Li {
916*600f14f4SXin Li printf("simple iterator on writable file\n");
917*600f14f4SXin Li
918*600f14f4SXin Li if(!change_stats_(flacfilename(/*is_ogg=*/false), /*read-only=*/false))
919*600f14f4SXin Li return false;
920*600f14f4SXin Li
921*600f14f4SXin Li printf("creating APPLICATION block\n");
922*600f14f4SXin Li
923*600f14f4SXin Li if(0 == (app = new FLAC::Metadata::Application()))
924*600f14f4SXin Li return die_("new FLAC::Metadata::Application()");
925*600f14f4SXin Li app->set_id((const uint8_t *)"duh");
926*600f14f4SXin Li
927*600f14f4SXin Li printf("creating PADDING block\n");
928*600f14f4SXin Li
929*600f14f4SXin Li if(0 == (padding = new FLAC::Metadata::Padding())) {
930*600f14f4SXin Li delete app;
931*600f14f4SXin Li return die_("new FLAC::Metadata::Padding()");
932*600f14f4SXin Li }
933*600f14f4SXin Li padding->set_length(20);
934*600f14f4SXin Li
935*600f14f4SXin Li FLAC::Metadata::SimpleIterator iterator;
936*600f14f4SXin Li
937*600f14f4SXin Li if(!iterator.is_valid()) {
938*600f14f4SXin Li delete app;
939*600f14f4SXin Li delete padding;
940*600f14f4SXin Li return die_("iterator.is_valid() returned false");
941*600f14f4SXin Li }
942*600f14f4SXin Li
943*600f14f4SXin Li if(!iterator.init(flacfilename(/*is_ogg=*/false), /*read_only=*/false, /*preserve_file_stats=*/false)) {
944*600f14f4SXin Li delete app;
945*600f14f4SXin Li delete padding;
946*600f14f4SXin Li return die_("iterator.init() returned false");
947*600f14f4SXin Li }
948*600f14f4SXin Li our_current_position = 0;
949*600f14f4SXin Li
950*600f14f4SXin Li printf("is writable = %u\n", (uint32_t)iterator.is_writable());
951*600f14f4SXin Li
952*600f14f4SXin Li printf("[S]VP\ttry to write over STREAMINFO block...\n");
953*600f14f4SXin Li if(!iterator.set_block(app, false))
954*600f14f4SXin Li printf("\titerator.set_block() returned false like it should\n");
955*600f14f4SXin Li else {
956*600f14f4SXin Li delete app;
957*600f14f4SXin Li delete padding;
958*600f14f4SXin Li return die_("iterator.set_block() returned true but shouldn't have");
959*600f14f4SXin Li }
960*600f14f4SXin Li
961*600f14f4SXin Li if(iterator.status() != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT)
962*600f14f4SXin Li return die_("iterator.status() should have been FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT");
963*600f14f4SXin Li
964*600f14f4SXin Li printf("[S]VP\tnext\n");
965*600f14f4SXin Li if(!iterator.next()) {
966*600f14f4SXin Li delete app;
967*600f14f4SXin Li delete padding;
968*600f14f4SXin Li return die_("iterator ended early\n");
969*600f14f4SXin Li }
970*600f14f4SXin Li our_current_position++;
971*600f14f4SXin Li
972*600f14f4SXin Li printf("S[V]P\tnext\n");
973*600f14f4SXin Li if(!iterator.next()) {
974*600f14f4SXin Li delete app;
975*600f14f4SXin Li delete padding;
976*600f14f4SXin Li return die_("iterator ended early\n");
977*600f14f4SXin Li }
978*600f14f4SXin Li our_current_position++;
979*600f14f4SXin Li
980*600f14f4SXin Li printf("SV[P]\tinsert PADDING after, don't expand into padding\n");
981*600f14f4SXin Li padding->set_length(25);
982*600f14f4SXin Li if(!iterator.insert_block_after(padding, false))
983*600f14f4SXin Li return die_ss_("iterator.insert_block_after(padding, false)", iterator);
984*600f14f4SXin Li if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
985*600f14f4SXin Li return false;
986*600f14f4SXin Li
987*600f14f4SXin Li printf("SVP[P]\tprev\n");
988*600f14f4SXin Li if(!iterator.prev())
989*600f14f4SXin Li return die_("iterator ended early\n");
990*600f14f4SXin Li our_current_position--;
991*600f14f4SXin Li
992*600f14f4SXin Li printf("SV[P]P\tprev\n");
993*600f14f4SXin Li if(!iterator.prev())
994*600f14f4SXin Li return die_("iterator ended early\n");
995*600f14f4SXin Li our_current_position--;
996*600f14f4SXin Li
997*600f14f4SXin Li printf("S[V]PP\tinsert PADDING after, don't expand into padding\n");
998*600f14f4SXin Li padding->set_length(30);
999*600f14f4SXin Li if(!iterator.insert_block_after(padding, false))
1000*600f14f4SXin Li return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1001*600f14f4SXin Li if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1002*600f14f4SXin Li return false;
1003*600f14f4SXin Li
1004*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1005*600f14f4SXin Li return false;
1006*600f14f4SXin Li
1007*600f14f4SXin Li printf("SV[P]PP\tprev\n");
1008*600f14f4SXin Li if(!iterator.prev())
1009*600f14f4SXin Li return die_("iterator ended early\n");
1010*600f14f4SXin Li our_current_position--;
1011*600f14f4SXin Li
1012*600f14f4SXin Li printf("S[V]PPP\tprev\n");
1013*600f14f4SXin Li if(!iterator.prev())
1014*600f14f4SXin Li return die_("iterator ended early\n");
1015*600f14f4SXin Li our_current_position--;
1016*600f14f4SXin Li
1017*600f14f4SXin Li printf("[S]VPPP\tdelete (STREAMINFO block), must fail\n");
1018*600f14f4SXin Li if(iterator.delete_block(false))
1019*600f14f4SXin Li return die_ss_("iterator.delete_block(false) should have returned false", iterator);
1020*600f14f4SXin Li
1021*600f14f4SXin Li if(iterator.status() != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT)
1022*600f14f4SXin Li return die_("iterator.status() should have been FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT");
1023*600f14f4SXin Li
1024*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1025*600f14f4SXin Li return false;
1026*600f14f4SXin Li
1027*600f14f4SXin Li printf("[S]VPPP\tnext\n");
1028*600f14f4SXin Li if(!iterator.next())
1029*600f14f4SXin Li return die_("iterator ended early\n");
1030*600f14f4SXin Li our_current_position++;
1031*600f14f4SXin Li
1032*600f14f4SXin Li printf("S[V]PPP\tnext\n");
1033*600f14f4SXin Li if(!iterator.next())
1034*600f14f4SXin Li return die_("iterator ended early\n");
1035*600f14f4SXin Li our_current_position++;
1036*600f14f4SXin Li
1037*600f14f4SXin Li printf("SV[P]PP\tdelete (middle block), replace with padding\n");
1038*600f14f4SXin Li if(!iterator.delete_block(true))
1039*600f14f4SXin Li return die_ss_("iterator.delete_block(true)", iterator);
1040*600f14f4SXin Li our_current_position--;
1041*600f14f4SXin Li
1042*600f14f4SXin Li printf("S[V]PPP\tnext\n");
1043*600f14f4SXin Li if(!iterator.next())
1044*600f14f4SXin Li return die_("iterator ended early\n");
1045*600f14f4SXin Li our_current_position++;
1046*600f14f4SXin Li
1047*600f14f4SXin Li printf("SV[P]PP\tdelete (middle block), don't replace with padding\n");
1048*600f14f4SXin Li if(!iterator.delete_block(false))
1049*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1050*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1051*600f14f4SXin Li
1052*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1053*600f14f4SXin Li return false;
1054*600f14f4SXin Li
1055*600f14f4SXin Li printf("S[V]PP\tnext\n");
1056*600f14f4SXin Li if(!iterator.next())
1057*600f14f4SXin Li return die_("iterator ended early\n");
1058*600f14f4SXin Li our_current_position++;
1059*600f14f4SXin Li
1060*600f14f4SXin Li printf("SV[P]P\tnext\n");
1061*600f14f4SXin Li if(!iterator.next())
1062*600f14f4SXin Li return die_("iterator ended early\n");
1063*600f14f4SXin Li our_current_position++;
1064*600f14f4SXin Li
1065*600f14f4SXin Li printf("SVP[P]\tdelete (last block), replace with padding\n");
1066*600f14f4SXin Li if(!iterator.delete_block(true))
1067*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1068*600f14f4SXin Li our_current_position--;
1069*600f14f4SXin Li
1070*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1071*600f14f4SXin Li return false;
1072*600f14f4SXin Li
1073*600f14f4SXin Li printf("SV[P]P\tnext\n");
1074*600f14f4SXin Li if(!iterator.next())
1075*600f14f4SXin Li return die_("iterator ended early\n");
1076*600f14f4SXin Li our_current_position++;
1077*600f14f4SXin Li
1078*600f14f4SXin Li printf("SVP[P]\tdelete (last block), don't replace with padding\n");
1079*600f14f4SXin Li if(!iterator.delete_block(false))
1080*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1081*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1082*600f14f4SXin Li
1083*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1084*600f14f4SXin Li return false;
1085*600f14f4SXin Li
1086*600f14f4SXin Li printf("SV[P]\tprev\n");
1087*600f14f4SXin Li if(!iterator.prev())
1088*600f14f4SXin Li return die_("iterator ended early\n");
1089*600f14f4SXin Li our_current_position--;
1090*600f14f4SXin Li
1091*600f14f4SXin Li printf("S[V]P\tprev\n");
1092*600f14f4SXin Li if(!iterator.prev())
1093*600f14f4SXin Li return die_("iterator ended early\n");
1094*600f14f4SXin Li our_current_position--;
1095*600f14f4SXin Li
1096*600f14f4SXin Li printf("[S]VP\tset STREAMINFO (change sample rate)\n");
1097*600f14f4SXin Li FLAC__ASSERT(our_current_position == 0);
1098*600f14f4SXin Li block = iterator.get_block();
1099*600f14f4SXin Li streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
1100*600f14f4SXin Li FLAC__ASSERT(0 != streaminfo);
1101*600f14f4SXin Li streaminfo->set_sample_rate(32000);
1102*600f14f4SXin Li if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1103*600f14f4SXin Li return die_("copying object");
1104*600f14f4SXin Li if(!iterator.set_block(block, false))
1105*600f14f4SXin Li return die_ss_("iterator.set_block(block, false)", iterator);
1106*600f14f4SXin Li delete block;
1107*600f14f4SXin Li
1108*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1109*600f14f4SXin Li return false;
1110*600f14f4SXin Li
1111*600f14f4SXin Li printf("[S]VP\tnext\n");
1112*600f14f4SXin Li if(!iterator.next())
1113*600f14f4SXin Li return die_("iterator ended early\n");
1114*600f14f4SXin Li our_current_position++;
1115*600f14f4SXin Li
1116*600f14f4SXin Li printf("S[V]P\tinsert APPLICATION after, expand into padding of exceeding size\n");
1117*600f14f4SXin Li app->set_id((const uint8_t *)"euh"); /* twiddle the id so that our comparison doesn't miss transposition */
1118*600f14f4SXin Li if(!iterator.insert_block_after(app, true))
1119*600f14f4SXin Li return die_ss_("iterator.insert_block_after(app, true)", iterator);
1120*600f14f4SXin Li if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1121*600f14f4SXin Li return false;
1122*600f14f4SXin Li add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
1123*600f14f4SXin Li
1124*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1125*600f14f4SXin Li return false;
1126*600f14f4SXin Li
1127*600f14f4SXin Li printf("SV[A]P\tnext\n");
1128*600f14f4SXin Li if(!iterator.next())
1129*600f14f4SXin Li return die_("iterator ended early\n");
1130*600f14f4SXin Li our_current_position++;
1131*600f14f4SXin Li
1132*600f14f4SXin Li printf("SVA[P]\tset APPLICATION, expand into padding of exceeding size\n");
1133*600f14f4SXin Li app->set_id((const uint8_t *)"fuh"); /* twiddle the id */
1134*600f14f4SXin Li if(!iterator.set_block(app, true))
1135*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1136*600f14f4SXin Li if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
1137*600f14f4SXin Li return false;
1138*600f14f4SXin Li add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
1139*600f14f4SXin Li
1140*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1141*600f14f4SXin Li return false;
1142*600f14f4SXin Li
1143*600f14f4SXin Li printf("SVA[A]P\tset APPLICATION (grow), don't expand into padding\n");
1144*600f14f4SXin Li app->set_id((const uint8_t *)"guh"); /* twiddle the id */
1145*600f14f4SXin Li if(!app->set_data(data, sizeof(data), true))
1146*600f14f4SXin Li return die_("setting APPLICATION data");
1147*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1148*600f14f4SXin Li return die_("copying object");
1149*600f14f4SXin Li if(!iterator.set_block(app, false))
1150*600f14f4SXin Li return die_ss_("iterator.set_block(app, false)", iterator);
1151*600f14f4SXin Li
1152*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1153*600f14f4SXin Li return false;
1154*600f14f4SXin Li
1155*600f14f4SXin Li printf("SVA[A]P\tset APPLICATION (shrink), don't fill in with padding\n");
1156*600f14f4SXin Li app->set_id((const uint8_t *)"huh"); /* twiddle the id */
1157*600f14f4SXin Li if(!app->set_data(data, 12, true))
1158*600f14f4SXin Li return die_("setting APPLICATION data");
1159*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1160*600f14f4SXin Li return die_("copying object");
1161*600f14f4SXin Li if(!iterator.set_block(app, false))
1162*600f14f4SXin Li return die_ss_("iterator.set_block(app, false)", iterator);
1163*600f14f4SXin Li
1164*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1165*600f14f4SXin Li return false;
1166*600f14f4SXin Li
1167*600f14f4SXin Li printf("SVA[A]P\tset APPLICATION (grow), expand into padding of exceeding size\n");
1168*600f14f4SXin Li app->set_id((const uint8_t *)"iuh"); /* twiddle the id */
1169*600f14f4SXin Li if(!app->set_data(data, sizeof(data), true))
1170*600f14f4SXin Li return die_("setting APPLICATION data");
1171*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1172*600f14f4SXin Li return die_("copying object");
1173*600f14f4SXin Li add_to_padding_length_(our_current_position+1, -((int)sizeof(data) - 12));
1174*600f14f4SXin Li if(!iterator.set_block(app, true))
1175*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1176*600f14f4SXin Li
1177*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1178*600f14f4SXin Li return false;
1179*600f14f4SXin Li
1180*600f14f4SXin Li printf("SVA[A]P\tset APPLICATION (shrink), fill in with padding\n");
1181*600f14f4SXin Li app->set_id((const uint8_t *)"juh"); /* twiddle the id */
1182*600f14f4SXin Li if(!app->set_data(data, 23, true))
1183*600f14f4SXin Li return die_("setting APPLICATION data");
1184*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1185*600f14f4SXin Li return die_("copying object");
1186*600f14f4SXin Li if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
1187*600f14f4SXin Li return die_("copying object");
1188*600f14f4SXin Li dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH);
1189*600f14f4SXin Li if(!iterator.set_block(app, true))
1190*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1191*600f14f4SXin Li
1192*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1193*600f14f4SXin Li return false;
1194*600f14f4SXin Li
1195*600f14f4SXin Li printf("SVA[A]PP\tnext\n");
1196*600f14f4SXin Li if(!iterator.next())
1197*600f14f4SXin Li return die_("iterator ended early\n");
1198*600f14f4SXin Li our_current_position++;
1199*600f14f4SXin Li
1200*600f14f4SXin Li printf("SVAA[P]P\tnext\n");
1201*600f14f4SXin Li if(!iterator.next())
1202*600f14f4SXin Li return die_("iterator ended early\n");
1203*600f14f4SXin Li our_current_position++;
1204*600f14f4SXin Li
1205*600f14f4SXin Li printf("SVAAP[P]\tset PADDING (shrink), don't fill in with padding\n");
1206*600f14f4SXin Li padding->set_length(5);
1207*600f14f4SXin Li if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1208*600f14f4SXin Li return die_("copying object");
1209*600f14f4SXin Li if(!iterator.set_block(padding, false))
1210*600f14f4SXin Li return die_ss_("iterator.set_block(padding, false)", iterator);
1211*600f14f4SXin Li
1212*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1213*600f14f4SXin Li return false;
1214*600f14f4SXin Li
1215*600f14f4SXin Li printf("SVAAP[P]\tset APPLICATION (grow)\n");
1216*600f14f4SXin Li app->set_id((const uint8_t *)"kuh"); /* twiddle the id */
1217*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1218*600f14f4SXin Li return die_("copying object");
1219*600f14f4SXin Li if(!iterator.set_block(app, false))
1220*600f14f4SXin Li return die_ss_("iterator.set_block(app, false)", iterator);
1221*600f14f4SXin Li
1222*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1223*600f14f4SXin Li return false;
1224*600f14f4SXin Li
1225*600f14f4SXin Li printf("SVAAP[A]\tset PADDING (equal)\n");
1226*600f14f4SXin Li padding->set_length(27);
1227*600f14f4SXin Li if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1228*600f14f4SXin Li return die_("copying object");
1229*600f14f4SXin Li if(!iterator.set_block(padding, false))
1230*600f14f4SXin Li return die_ss_("iterator.set_block(padding, false)", iterator);
1231*600f14f4SXin Li
1232*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1233*600f14f4SXin Li return false;
1234*600f14f4SXin Li
1235*600f14f4SXin Li printf("SVAAP[P]\tprev\n");
1236*600f14f4SXin Li if(!iterator.prev())
1237*600f14f4SXin Li return die_("iterator ended early\n");
1238*600f14f4SXin Li our_current_position--;
1239*600f14f4SXin Li
1240*600f14f4SXin Li printf("SVAA[P]P\tdelete (middle block), don't replace with padding\n");
1241*600f14f4SXin Li if(!iterator.delete_block(false))
1242*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1243*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1244*600f14f4SXin Li
1245*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1246*600f14f4SXin Li return false;
1247*600f14f4SXin Li
1248*600f14f4SXin Li printf("SVA[A]P\tdelete (middle block), don't replace with padding\n");
1249*600f14f4SXin Li if(!iterator.delete_block(false))
1250*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1251*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1252*600f14f4SXin Li
1253*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1254*600f14f4SXin Li return false;
1255*600f14f4SXin Li
1256*600f14f4SXin Li printf("SV[A]P\tnext\n");
1257*600f14f4SXin Li if(!iterator.next())
1258*600f14f4SXin Li return die_("iterator ended early\n");
1259*600f14f4SXin Li our_current_position++;
1260*600f14f4SXin Li
1261*600f14f4SXin Li printf("SVA[P]\tinsert PADDING after\n");
1262*600f14f4SXin Li padding->set_length(5);
1263*600f14f4SXin Li if(!iterator.insert_block_after(padding, false))
1264*600f14f4SXin Li return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1265*600f14f4SXin Li if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1266*600f14f4SXin Li return false;
1267*600f14f4SXin Li
1268*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1269*600f14f4SXin Li return false;
1270*600f14f4SXin Li
1271*600f14f4SXin Li printf("SVAP[P]\tprev\n");
1272*600f14f4SXin Li if(!iterator.prev())
1273*600f14f4SXin Li return die_("iterator ended early\n");
1274*600f14f4SXin Li our_current_position--;
1275*600f14f4SXin Li
1276*600f14f4SXin Li printf("SVA[P]P\tprev\n");
1277*600f14f4SXin Li if(!iterator.prev())
1278*600f14f4SXin Li return die_("iterator ended early\n");
1279*600f14f4SXin Li our_current_position--;
1280*600f14f4SXin Li
1281*600f14f4SXin Li printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is too small\n");
1282*600f14f4SXin Li if(!app->set_data(data, 32, true))
1283*600f14f4SXin Li return die_("setting APPLICATION data");
1284*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1285*600f14f4SXin Li return die_("copying object");
1286*600f14f4SXin Li if(!iterator.set_block(app, true))
1287*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1288*600f14f4SXin Li
1289*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1290*600f14f4SXin Li return false;
1291*600f14f4SXin Li
1292*600f14f4SXin Li printf("SV[A]PP\tset APPLICATION (grow), try to expand into padding which is 'close' but still too small\n");
1293*600f14f4SXin Li if(!app->set_data(data, 60, true))
1294*600f14f4SXin Li return die_("setting APPLICATION data");
1295*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1296*600f14f4SXin Li return die_("copying object");
1297*600f14f4SXin Li if(!iterator.set_block(app, true))
1298*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1299*600f14f4SXin Li
1300*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1301*600f14f4SXin Li return false;
1302*600f14f4SXin Li
1303*600f14f4SXin Li printf("SV[A]PP\tset APPLICATION (grow), expand into padding which will leave 0-length pad\n");
1304*600f14f4SXin Li if(!app->set_data(data, 87, true))
1305*600f14f4SXin Li return die_("setting APPLICATION data");
1306*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1307*600f14f4SXin Li return die_("copying object");
1308*600f14f4SXin Li dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1309*600f14f4SXin Li if(!iterator.set_block(app, true))
1310*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1311*600f14f4SXin Li
1312*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1313*600f14f4SXin Li return false;
1314*600f14f4SXin Li
1315*600f14f4SXin Li printf("SV[A]PP\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1316*600f14f4SXin Li if(!app->set_data(data, 91, true))
1317*600f14f4SXin Li return die_("setting APPLICATION data");
1318*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1319*600f14f4SXin Li return die_("copying object");
1320*600f14f4SXin Li delete_from_our_metadata_(our_current_position+1);
1321*600f14f4SXin Li if(!iterator.set_block(app, true))
1322*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1323*600f14f4SXin Li
1324*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1325*600f14f4SXin Li return false;
1326*600f14f4SXin Li
1327*600f14f4SXin Li printf("SV[A]P\tset APPLICATION (grow), expand into padding which is exactly consumed\n");
1328*600f14f4SXin Li if(!app->set_data(data, 100, true))
1329*600f14f4SXin Li return die_("setting APPLICATION data");
1330*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1331*600f14f4SXin Li return die_("copying object");
1332*600f14f4SXin Li delete_from_our_metadata_(our_current_position+1);
1333*600f14f4SXin Li our_metadata_.blocks[our_current_position]->set_is_last(true);
1334*600f14f4SXin Li if(!iterator.set_block(app, true))
1335*600f14f4SXin Li return die_ss_("iterator.set_block(app, true)", iterator);
1336*600f14f4SXin Li
1337*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1338*600f14f4SXin Li return false;
1339*600f14f4SXin Li
1340*600f14f4SXin Li printf("SV[A]\tset PADDING (equal size)\n");
1341*600f14f4SXin Li padding->set_length(app->get_length());
1342*600f14f4SXin Li if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
1343*600f14f4SXin Li return die_("copying object");
1344*600f14f4SXin Li if(!iterator.set_block(padding, true))
1345*600f14f4SXin Li return die_ss_("iterator.set_block(padding, true)", iterator);
1346*600f14f4SXin Li
1347*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1348*600f14f4SXin Li return false;
1349*600f14f4SXin Li
1350*600f14f4SXin Li printf("SV[P]\tinsert PADDING after\n");
1351*600f14f4SXin Li if(!iterator.insert_block_after(padding, false))
1352*600f14f4SXin Li return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1353*600f14f4SXin Li if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1354*600f14f4SXin Li return false;
1355*600f14f4SXin Li
1356*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1357*600f14f4SXin Li return false;
1358*600f14f4SXin Li
1359*600f14f4SXin Li printf("SVP[P]\tinsert PADDING after\n");
1360*600f14f4SXin Li padding->set_length(5);
1361*600f14f4SXin Li if(!iterator.insert_block_after(padding, false))
1362*600f14f4SXin Li return die_ss_("iterator.insert_block_after(padding, false)", iterator);
1363*600f14f4SXin Li if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1364*600f14f4SXin Li return false;
1365*600f14f4SXin Li
1366*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1367*600f14f4SXin Li return false;
1368*600f14f4SXin Li
1369*600f14f4SXin Li printf("SVPP[P]\tprev\n");
1370*600f14f4SXin Li if(!iterator.prev())
1371*600f14f4SXin Li return die_("iterator ended early\n");
1372*600f14f4SXin Li our_current_position--;
1373*600f14f4SXin Li
1374*600f14f4SXin Li printf("SVP[P]P\tprev\n");
1375*600f14f4SXin Li if(!iterator.prev())
1376*600f14f4SXin Li return die_("iterator ended early\n");
1377*600f14f4SXin Li our_current_position--;
1378*600f14f4SXin Li
1379*600f14f4SXin Li printf("SV[P]PP\tprev\n");
1380*600f14f4SXin Li if(!iterator.prev())
1381*600f14f4SXin Li return die_("iterator ended early\n");
1382*600f14f4SXin Li our_current_position--;
1383*600f14f4SXin Li
1384*600f14f4SXin Li printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is too small\n");
1385*600f14f4SXin Li if(!app->set_data(data, 101, true))
1386*600f14f4SXin Li return die_("setting APPLICATION data");
1387*600f14f4SXin Li if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1388*600f14f4SXin Li return die_("copying object");
1389*600f14f4SXin Li if(!iterator.insert_block_after(app, true))
1390*600f14f4SXin Li return die_ss_("iterator.insert_block_after(app, true)", iterator);
1391*600f14f4SXin Li
1392*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1393*600f14f4SXin Li return false;
1394*600f14f4SXin Li
1395*600f14f4SXin Li printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1396*600f14f4SXin Li if(!iterator.delete_block(false))
1397*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1398*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1399*600f14f4SXin Li
1400*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1401*600f14f4SXin Li return false;
1402*600f14f4SXin Li
1403*600f14f4SXin Li printf("S[V]PPP\tinsert APPLICATION after, try to expand into padding which is 'close' but still too small\n");
1404*600f14f4SXin Li if(!app->set_data(data, 97, true))
1405*600f14f4SXin Li return die_("setting APPLICATION data");
1406*600f14f4SXin Li if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1407*600f14f4SXin Li return die_("copying object");
1408*600f14f4SXin Li if(!iterator.insert_block_after(app, true))
1409*600f14f4SXin Li return die_ss_("iterator.insert_block_after(app, true)", iterator);
1410*600f14f4SXin Li
1411*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1412*600f14f4SXin Li return false;
1413*600f14f4SXin Li
1414*600f14f4SXin Li printf("SV[A]PPP\tdelete (middle block), don't replace with padding\n");
1415*600f14f4SXin Li if(!iterator.delete_block(false))
1416*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1417*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1418*600f14f4SXin Li
1419*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1420*600f14f4SXin Li return false;
1421*600f14f4SXin Li
1422*600f14f4SXin Li printf("S[V]PPP\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1423*600f14f4SXin Li if(!app->set_data(data, 100, true))
1424*600f14f4SXin Li return die_("setting APPLICATION data");
1425*600f14f4SXin Li if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1426*600f14f4SXin Li return die_("copying object");
1427*600f14f4SXin Li delete_from_our_metadata_(our_current_position+1);
1428*600f14f4SXin Li if(!iterator.insert_block_after(app, true))
1429*600f14f4SXin Li return die_ss_("iterator.insert_block_after(app, true)", iterator);
1430*600f14f4SXin Li
1431*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1432*600f14f4SXin Li return false;
1433*600f14f4SXin Li
1434*600f14f4SXin Li printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1435*600f14f4SXin Li if(!iterator.delete_block(false))
1436*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1437*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1438*600f14f4SXin Li
1439*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1440*600f14f4SXin Li return false;
1441*600f14f4SXin Li
1442*600f14f4SXin Li printf("S[V]PP\tinsert APPLICATION after, expand into padding which will leave 0-length pad\n");
1443*600f14f4SXin Li if(!app->set_data(data, 96, true))
1444*600f14f4SXin Li return die_("setting APPLICATION data");
1445*600f14f4SXin Li if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1446*600f14f4SXin Li return die_("copying object");
1447*600f14f4SXin Li dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
1448*600f14f4SXin Li if(!iterator.insert_block_after(app, true))
1449*600f14f4SXin Li return die_ss_("iterator.insert_block_after(app, true)", iterator);
1450*600f14f4SXin Li
1451*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1452*600f14f4SXin Li return false;
1453*600f14f4SXin Li
1454*600f14f4SXin Li printf("SV[A]PP\tdelete (middle block), don't replace with padding\n");
1455*600f14f4SXin Li if(!iterator.delete_block(false))
1456*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1457*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1458*600f14f4SXin Li
1459*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1460*600f14f4SXin Li return false;
1461*600f14f4SXin Li
1462*600f14f4SXin Li printf("S[V]PP\tnext\n");
1463*600f14f4SXin Li if(!iterator.next())
1464*600f14f4SXin Li return die_("iterator ended early\n");
1465*600f14f4SXin Li our_current_position++;
1466*600f14f4SXin Li
1467*600f14f4SXin Li printf("SV[P]P\tdelete (middle block), don't replace with padding\n");
1468*600f14f4SXin Li if(!iterator.delete_block(false))
1469*600f14f4SXin Li return die_ss_("iterator.delete_block(false)", iterator);
1470*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1471*600f14f4SXin Li
1472*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1473*600f14f4SXin Li return false;
1474*600f14f4SXin Li
1475*600f14f4SXin Li printf("S[V]P\tinsert APPLICATION after, expand into padding which is exactly consumed\n");
1476*600f14f4SXin Li if(!app->set_data(data, 1, true))
1477*600f14f4SXin Li return die_("setting APPLICATION data");
1478*600f14f4SXin Li if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
1479*600f14f4SXin Li return die_("copying object");
1480*600f14f4SXin Li delete_from_our_metadata_(our_current_position+1);
1481*600f14f4SXin Li if(!iterator.insert_block_after(app, true))
1482*600f14f4SXin Li return die_ss_("iterator.insert_block_after(app, true)", iterator);
1483*600f14f4SXin Li
1484*600f14f4SXin Li if(!test_file_(/*is_ogg=*/false, /*ignore_metadata=*/false))
1485*600f14f4SXin Li return false;
1486*600f14f4SXin Li }
1487*600f14f4SXin Li
1488*600f14f4SXin Li delete app;
1489*600f14f4SXin Li delete padding;
1490*600f14f4SXin Li
1491*600f14f4SXin Li if(!remove_file_(flacfilename(/*is_ogg=*/false)))
1492*600f14f4SXin Li return false;
1493*600f14f4SXin Li
1494*600f14f4SXin Li return true;
1495*600f14f4SXin Li }
1496*600f14f4SXin Li
test_level_2_(bool filename_based,bool is_ogg)1497*600f14f4SXin Li static bool test_level_2_(bool filename_based, bool is_ogg)
1498*600f14f4SXin Li {
1499*600f14f4SXin Li FLAC::Metadata::Prototype *block;
1500*600f14f4SXin Li FLAC::Metadata::StreamInfo *streaminfo;
1501*600f14f4SXin Li FLAC::Metadata::Application *app;
1502*600f14f4SXin Li FLAC::Metadata::Padding *padding;
1503*600f14f4SXin Li FLAC__byte data[2000];
1504*600f14f4SXin Li uint32_t our_current_position;
1505*600f14f4SXin Li
1506*600f14f4SXin Li // initialize 'data' to avoid Valgrind errors
1507*600f14f4SXin Li memset(data, 0, sizeof(data));
1508*600f14f4SXin Li
1509*600f14f4SXin Li printf("\n\n++++++ testing level 2 interface (%s-based, %s FLAC)\n", filename_based? "filename":"callback", is_ogg? "Ogg":"native");
1510*600f14f4SXin Li
1511*600f14f4SXin Li printf("generate read-only file\n");
1512*600f14f4SXin Li
1513*600f14f4SXin Li if(!generate_file_(/*include_extras=*/false, is_ogg))
1514*600f14f4SXin Li return false;
1515*600f14f4SXin Li
1516*600f14f4SXin Li if(!change_stats_(flacfilename(is_ogg), /*read_only=*/true))
1517*600f14f4SXin Li return false;
1518*600f14f4SXin Li
1519*600f14f4SXin Li printf("create chain\n");
1520*600f14f4SXin Li FLAC::Metadata::Chain chain;
1521*600f14f4SXin Li if(!chain.is_valid())
1522*600f14f4SXin Li return die_("allocating memory for chain");
1523*600f14f4SXin Li
1524*600f14f4SXin Li printf("read chain\n");
1525*600f14f4SXin Li
1526*600f14f4SXin Li if(!read_chain_(chain, flacfilename(is_ogg), filename_based, is_ogg))
1527*600f14f4SXin Li return die_c_("reading chain", chain.status());
1528*600f14f4SXin Li
1529*600f14f4SXin Li printf("[S]VP\ttest initial metadata\n");
1530*600f14f4SXin Li
1531*600f14f4SXin Li if(!compare_chain_(chain, 0, 0))
1532*600f14f4SXin Li return false;
1533*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1534*600f14f4SXin Li return false;
1535*600f14f4SXin Li
1536*600f14f4SXin Li if(is_ogg)
1537*600f14f4SXin Li goto end;
1538*600f14f4SXin Li
1539*600f14f4SXin Li printf("switch file to read-write\n");
1540*600f14f4SXin Li
1541*600f14f4SXin Li if(!change_stats_(flacfilename(is_ogg), /*read-only=*/false))
1542*600f14f4SXin Li return false;
1543*600f14f4SXin Li
1544*600f14f4SXin Li printf("create iterator\n");
1545*600f14f4SXin Li {
1546*600f14f4SXin Li FLAC::Metadata::Iterator iterator;
1547*600f14f4SXin Li if(!iterator.is_valid())
1548*600f14f4SXin Li return die_("allocating memory for iterator");
1549*600f14f4SXin Li
1550*600f14f4SXin Li our_current_position = 0;
1551*600f14f4SXin Li
1552*600f14f4SXin Li iterator.init(chain);
1553*600f14f4SXin Li
1554*600f14f4SXin Li if(0 == (block = iterator.get_block()))
1555*600f14f4SXin Li return die_("getting block from iterator");
1556*600f14f4SXin Li
1557*600f14f4SXin Li FLAC__ASSERT(block->get_type() == FLAC__METADATA_TYPE_STREAMINFO);
1558*600f14f4SXin Li
1559*600f14f4SXin Li printf("[S]VP\tmodify STREAMINFO, write\n");
1560*600f14f4SXin Li
1561*600f14f4SXin Li streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
1562*600f14f4SXin Li FLAC__ASSERT(0 != streaminfo);
1563*600f14f4SXin Li streaminfo->set_sample_rate(32000);
1564*600f14f4SXin Li if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
1565*600f14f4SXin Li return die_("copying object");
1566*600f14f4SXin Li delete block;
1567*600f14f4SXin Li
1568*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfilename(is_ogg)))
1569*600f14f4SXin Li return die_c_("during chain.write(false, true)", chain.status());
1570*600f14f4SXin Li block = iterator.get_block();
1571*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1572*600f14f4SXin Li return false;
1573*600f14f4SXin Li delete block;
1574*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1575*600f14f4SXin Li return false;
1576*600f14f4SXin Li
1577*600f14f4SXin Li printf("[S]VP\tnext\n");
1578*600f14f4SXin Li if(!iterator.next())
1579*600f14f4SXin Li return die_("iterator ended early\n");
1580*600f14f4SXin Li our_current_position++;
1581*600f14f4SXin Li
1582*600f14f4SXin Li printf("S[V]P\tnext\n");
1583*600f14f4SXin Li if(!iterator.next())
1584*600f14f4SXin Li return die_("iterator ended early\n");
1585*600f14f4SXin Li our_current_position++;
1586*600f14f4SXin Li
1587*600f14f4SXin Li printf("SV[P]\treplace PADDING with identical-size APPLICATION\n");
1588*600f14f4SXin Li if(0 == (block = iterator.get_block()))
1589*600f14f4SXin Li return die_("getting block from iterator");
1590*600f14f4SXin Li if(0 == (app = new FLAC::Metadata::Application()))
1591*600f14f4SXin Li return die_("new FLAC::Metadata::Application()");
1592*600f14f4SXin Li app->set_id((const uint8_t *)"duh");
1593*600f14f4SXin Li if(!app->set_data(data, block->get_length()-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
1594*600f14f4SXin Li return die_("setting APPLICATION data");
1595*600f14f4SXin Li delete block;
1596*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1597*600f14f4SXin Li return die_("copying object");
1598*600f14f4SXin Li if(!iterator.set_block(app))
1599*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1600*600f14f4SXin Li
1601*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1602*600f14f4SXin Li return die_c_("during chain.write(false, false)", chain.status());
1603*600f14f4SXin Li block = iterator.get_block();
1604*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1605*600f14f4SXin Li return false;
1606*600f14f4SXin Li delete block;
1607*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1608*600f14f4SXin Li return false;
1609*600f14f4SXin Li
1610*600f14f4SXin Li printf("SV[A]\tshrink APPLICATION, don't use padding\n");
1611*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1612*600f14f4SXin Li return die_("copying object");
1613*600f14f4SXin Li if(!app->set_data(data, 26, true))
1614*600f14f4SXin Li return die_("setting APPLICATION data");
1615*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1616*600f14f4SXin Li return die_("copying object");
1617*600f14f4SXin Li if(!iterator.set_block(app))
1618*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1619*600f14f4SXin Li
1620*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1621*600f14f4SXin Li return die_c_("during chain.write(false, false)", chain.status());
1622*600f14f4SXin Li block = iterator.get_block();
1623*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1624*600f14f4SXin Li return false;
1625*600f14f4SXin Li delete block;
1626*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1627*600f14f4SXin Li return false;
1628*600f14f4SXin Li
1629*600f14f4SXin Li printf("SV[A]\tgrow APPLICATION, don't use padding\n");
1630*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1631*600f14f4SXin Li return die_("copying object");
1632*600f14f4SXin Li if(!app->set_data(data, 28, true))
1633*600f14f4SXin Li return die_("setting APPLICATION data");
1634*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1635*600f14f4SXin Li return die_("copying object");
1636*600f14f4SXin Li if(!iterator.set_block(app))
1637*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1638*600f14f4SXin Li
1639*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1640*600f14f4SXin Li return die_c_("during chain.write(false, false)", chain.status());
1641*600f14f4SXin Li block = iterator.get_block();
1642*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1643*600f14f4SXin Li return false;
1644*600f14f4SXin Li delete block;
1645*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1646*600f14f4SXin Li return false;
1647*600f14f4SXin Li
1648*600f14f4SXin Li printf("SV[A]\tgrow APPLICATION, use padding, but last block is not padding\n");
1649*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1650*600f14f4SXin Li return die_("copying object");
1651*600f14f4SXin Li if(!app->set_data(data, 36, true))
1652*600f14f4SXin Li return die_("setting APPLICATION data");
1653*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1654*600f14f4SXin Li return die_("copying object");
1655*600f14f4SXin Li if(!iterator.set_block(app))
1656*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1657*600f14f4SXin Li
1658*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1659*600f14f4SXin Li return die_c_("during chain.write(false, false)", chain.status());
1660*600f14f4SXin Li block = iterator.get_block();
1661*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1662*600f14f4SXin Li return false;
1663*600f14f4SXin Li delete block;
1664*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1665*600f14f4SXin Li return false;
1666*600f14f4SXin Li
1667*600f14f4SXin Li printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING block\n");
1668*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1669*600f14f4SXin Li return die_("copying object");
1670*600f14f4SXin Li if(!app->set_data(data, 33, true))
1671*600f14f4SXin Li return die_("setting APPLICATION data");
1672*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1673*600f14f4SXin Li return die_("copying object");
1674*600f14f4SXin Li if(!iterator.set_block(app))
1675*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1676*600f14f4SXin Li
1677*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1678*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1679*600f14f4SXin Li block = iterator.get_block();
1680*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1681*600f14f4SXin Li return false;
1682*600f14f4SXin Li delete block;
1683*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1684*600f14f4SXin Li return false;
1685*600f14f4SXin Li
1686*600f14f4SXin Li printf("SV[A]\tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING block\n");
1687*600f14f4SXin Li if(0 == (padding = new FLAC::Metadata::Padding()))
1688*600f14f4SXin Li return die_("creating PADDING block");
1689*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1690*600f14f4SXin Li return die_("copying object");
1691*600f14f4SXin Li if(!app->set_data(data, 29, true))
1692*600f14f4SXin Li return die_("setting APPLICATION data");
1693*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1694*600f14f4SXin Li return die_("copying object");
1695*600f14f4SXin Li padding->set_length(0);
1696*600f14f4SXin Li if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
1697*600f14f4SXin Li return die_("internal error");
1698*600f14f4SXin Li if(!iterator.set_block(app))
1699*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1700*600f14f4SXin Li
1701*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1702*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1703*600f14f4SXin Li block = iterator.get_block();
1704*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1705*600f14f4SXin Li return false;
1706*600f14f4SXin Li delete block;
1707*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1708*600f14f4SXin Li return false;
1709*600f14f4SXin Li
1710*600f14f4SXin Li printf("SV[A]P\tshrink APPLICATION, use padding, last block is padding\n");
1711*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1712*600f14f4SXin Li return die_("copying object");
1713*600f14f4SXin Li if(!app->set_data(data, 16, true))
1714*600f14f4SXin Li return die_("setting APPLICATION data");
1715*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1716*600f14f4SXin Li return die_("copying object");
1717*600f14f4SXin Li dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(13);
1718*600f14f4SXin Li if(!iterator.set_block(app))
1719*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1720*600f14f4SXin Li
1721*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1722*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1723*600f14f4SXin Li block = iterator.get_block();
1724*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1725*600f14f4SXin Li return false;
1726*600f14f4SXin Li delete block;
1727*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1728*600f14f4SXin Li return false;
1729*600f14f4SXin Li
1730*600f14f4SXin Li printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding, but delta is too small\n");
1731*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1732*600f14f4SXin Li return die_("copying object");
1733*600f14f4SXin Li if(!app->set_data(data, 50, true))
1734*600f14f4SXin Li return die_("setting APPLICATION data");
1735*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1736*600f14f4SXin Li return die_("copying object");
1737*600f14f4SXin Li if(!iterator.set_block(app))
1738*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1739*600f14f4SXin Li
1740*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1741*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1742*600f14f4SXin Li block = iterator.get_block();
1743*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1744*600f14f4SXin Li return false;
1745*600f14f4SXin Li delete block;
1746*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1747*600f14f4SXin Li return false;
1748*600f14f4SXin Li
1749*600f14f4SXin Li printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exceeding size\n");
1750*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1751*600f14f4SXin Li return die_("copying object");
1752*600f14f4SXin Li if(!app->set_data(data, 56, true))
1753*600f14f4SXin Li return die_("setting APPLICATION data");
1754*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1755*600f14f4SXin Li return die_("copying object");
1756*600f14f4SXin Li add_to_padding_length_(our_current_position+1, -(56 - 50));
1757*600f14f4SXin Li if(!iterator.set_block(app))
1758*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1759*600f14f4SXin Li
1760*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1761*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1762*600f14f4SXin Li block = iterator.get_block();
1763*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1764*600f14f4SXin Li return false;
1765*600f14f4SXin Li delete block;
1766*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1767*600f14f4SXin Li return false;
1768*600f14f4SXin Li
1769*600f14f4SXin Li printf("SV[A]P\tgrow APPLICATION, use padding, last block is padding of exact size\n");
1770*600f14f4SXin Li if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1771*600f14f4SXin Li return die_("copying object");
1772*600f14f4SXin Li if(!app->set_data(data, 67, true))
1773*600f14f4SXin Li return die_("setting APPLICATION data");
1774*600f14f4SXin Li if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
1775*600f14f4SXin Li return die_("copying object");
1776*600f14f4SXin Li delete_from_our_metadata_(our_current_position+1);
1777*600f14f4SXin Li if(!iterator.set_block(app))
1778*600f14f4SXin Li return die_c_("iterator.set_block(app)", chain.status());
1779*600f14f4SXin Li
1780*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1781*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1782*600f14f4SXin Li block = iterator.get_block();
1783*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1784*600f14f4SXin Li return false;
1785*600f14f4SXin Li delete block;
1786*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1787*600f14f4SXin Li return false;
1788*600f14f4SXin Li
1789*600f14f4SXin Li printf("SV[A]\tprev\n");
1790*600f14f4SXin Li if(!iterator.prev())
1791*600f14f4SXin Li return die_("iterator ended early\n");
1792*600f14f4SXin Li our_current_position--;
1793*600f14f4SXin Li
1794*600f14f4SXin Li printf("S[V]A\tprev\n");
1795*600f14f4SXin Li if(!iterator.prev())
1796*600f14f4SXin Li return die_("iterator ended early\n");
1797*600f14f4SXin Li our_current_position--;
1798*600f14f4SXin Li
1799*600f14f4SXin Li printf("[S]VA\tinsert PADDING before STREAMINFO (should fail)\n");
1800*600f14f4SXin Li if(0 == (padding = new FLAC::Metadata::Padding()))
1801*600f14f4SXin Li return die_("creating PADDING block");
1802*600f14f4SXin Li padding->set_length(30);
1803*600f14f4SXin Li if(!iterator.insert_block_before(padding))
1804*600f14f4SXin Li printf("\titerator.insert_block_before() returned false like it should\n");
1805*600f14f4SXin Li else
1806*600f14f4SXin Li return die_("iterator.insert_block_before() should have returned false");
1807*600f14f4SXin Li
1808*600f14f4SXin Li printf("[S]VA\tnext\n");
1809*600f14f4SXin Li if(!iterator.next())
1810*600f14f4SXin Li return die_("iterator ended early\n");
1811*600f14f4SXin Li our_current_position++;
1812*600f14f4SXin Li
1813*600f14f4SXin Li printf("S[V]A\tinsert PADDING after\n");
1814*600f14f4SXin Li if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1815*600f14f4SXin Li return die_("copying metadata");
1816*600f14f4SXin Li if(!iterator.insert_block_after(padding))
1817*600f14f4SXin Li return die_("iterator.insert_block_after(padding)");
1818*600f14f4SXin Li
1819*600f14f4SXin Li block = iterator.get_block();
1820*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1821*600f14f4SXin Li return false;
1822*600f14f4SXin Li delete block;
1823*600f14f4SXin Li
1824*600f14f4SXin Li printf("SV[P]A\tinsert PADDING before\n");
1825*600f14f4SXin Li if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1826*600f14f4SXin Li return die_("creating PADDING block");
1827*600f14f4SXin Li padding->set_length(17);
1828*600f14f4SXin Li if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1829*600f14f4SXin Li return die_("copying metadata");
1830*600f14f4SXin Li if(!iterator.insert_block_before(padding))
1831*600f14f4SXin Li return die_("iterator.insert_block_before(padding)");
1832*600f14f4SXin Li
1833*600f14f4SXin Li block = iterator.get_block();
1834*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1835*600f14f4SXin Li return false;
1836*600f14f4SXin Li delete block;
1837*600f14f4SXin Li
1838*600f14f4SXin Li printf("SV[P]PA\tinsert PADDING before\n");
1839*600f14f4SXin Li if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
1840*600f14f4SXin Li return die_("creating PADDING block");
1841*600f14f4SXin Li padding->set_length(0);
1842*600f14f4SXin Li if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1843*600f14f4SXin Li return die_("copying metadata");
1844*600f14f4SXin Li if(!iterator.insert_block_before(padding))
1845*600f14f4SXin Li return die_("iterator.insert_block_before(padding)");
1846*600f14f4SXin Li
1847*600f14f4SXin Li block = iterator.get_block();
1848*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1849*600f14f4SXin Li return false;
1850*600f14f4SXin Li delete block;
1851*600f14f4SXin Li
1852*600f14f4SXin Li printf("SV[P]PPA\tnext\n");
1853*600f14f4SXin Li if(!iterator.next())
1854*600f14f4SXin Li return die_("iterator ended early\n");
1855*600f14f4SXin Li our_current_position++;
1856*600f14f4SXin Li
1857*600f14f4SXin Li printf("SVP[P]PA\tnext\n");
1858*600f14f4SXin Li if(!iterator.next())
1859*600f14f4SXin Li return die_("iterator ended early\n");
1860*600f14f4SXin Li our_current_position++;
1861*600f14f4SXin Li
1862*600f14f4SXin Li printf("SVPP[P]A\tnext\n");
1863*600f14f4SXin Li if(!iterator.next())
1864*600f14f4SXin Li return die_("iterator ended early\n");
1865*600f14f4SXin Li our_current_position++;
1866*600f14f4SXin Li
1867*600f14f4SXin Li printf("SVPPP[A]\tinsert PADDING after\n");
1868*600f14f4SXin Li if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1869*600f14f4SXin Li return die_("creating PADDING block");
1870*600f14f4SXin Li padding->set_length(57);
1871*600f14f4SXin Li if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
1872*600f14f4SXin Li return die_("copying metadata");
1873*600f14f4SXin Li if(!iterator.insert_block_after(padding))
1874*600f14f4SXin Li return die_("iterator.insert_block_after(padding)");
1875*600f14f4SXin Li
1876*600f14f4SXin Li block = iterator.get_block();
1877*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1878*600f14f4SXin Li return false;
1879*600f14f4SXin Li delete block;
1880*600f14f4SXin Li
1881*600f14f4SXin Li printf("SVPPPA[P]\tinsert PADDING before\n");
1882*600f14f4SXin Li if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
1883*600f14f4SXin Li return die_("creating PADDING block");
1884*600f14f4SXin Li padding->set_length(99);
1885*600f14f4SXin Li if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
1886*600f14f4SXin Li return die_("copying metadata");
1887*600f14f4SXin Li if(!iterator.insert_block_before(padding))
1888*600f14f4SXin Li return die_("iterator.insert_block_before(padding)");
1889*600f14f4SXin Li
1890*600f14f4SXin Li block = iterator.get_block();
1891*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1892*600f14f4SXin Li return false;
1893*600f14f4SXin Li delete block;
1894*600f14f4SXin Li
1895*600f14f4SXin Li }
1896*600f14f4SXin Li our_current_position = 0;
1897*600f14f4SXin Li
1898*600f14f4SXin Li printf("SVPPPAPP\tmerge padding\n");
1899*600f14f4SXin Li chain.merge_padding();
1900*600f14f4SXin Li add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->get_length());
1901*600f14f4SXin Li add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->get_length());
1902*600f14f4SXin Li add_to_padding_length_(6, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->get_length());
1903*600f14f4SXin Li delete_from_our_metadata_(7);
1904*600f14f4SXin Li delete_from_our_metadata_(4);
1905*600f14f4SXin Li delete_from_our_metadata_(3);
1906*600f14f4SXin Li
1907*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1908*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1909*600f14f4SXin Li if(!compare_chain_(chain, 0, 0))
1910*600f14f4SXin Li return false;
1911*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1912*600f14f4SXin Li return false;
1913*600f14f4SXin Li
1914*600f14f4SXin Li printf("SVPAP\tsort padding\n");
1915*600f14f4SXin Li chain.sort_padding();
1916*600f14f4SXin Li add_to_padding_length_(4, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->get_length());
1917*600f14f4SXin Li delete_from_our_metadata_(2);
1918*600f14f4SXin Li
1919*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
1920*600f14f4SXin Li return die_c_("during chain.write(true, false)", chain.status());
1921*600f14f4SXin Li if(!compare_chain_(chain, 0, 0))
1922*600f14f4SXin Li return false;
1923*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
1924*600f14f4SXin Li return false;
1925*600f14f4SXin Li
1926*600f14f4SXin Li printf("create iterator\n");
1927*600f14f4SXin Li {
1928*600f14f4SXin Li FLAC::Metadata::Iterator iterator;
1929*600f14f4SXin Li if(!iterator.is_valid())
1930*600f14f4SXin Li return die_("allocating memory for iterator");
1931*600f14f4SXin Li
1932*600f14f4SXin Li our_current_position = 0;
1933*600f14f4SXin Li
1934*600f14f4SXin Li iterator.init(chain);
1935*600f14f4SXin Li
1936*600f14f4SXin Li printf("[S]VAP\tnext\n");
1937*600f14f4SXin Li if(!iterator.next())
1938*600f14f4SXin Li return die_("iterator ended early\n");
1939*600f14f4SXin Li our_current_position++;
1940*600f14f4SXin Li
1941*600f14f4SXin Li printf("S[V]AP\tnext\n");
1942*600f14f4SXin Li if(!iterator.next())
1943*600f14f4SXin Li return die_("iterator ended early\n");
1944*600f14f4SXin Li our_current_position++;
1945*600f14f4SXin Li
1946*600f14f4SXin Li printf("SV[A]P\tdelete middle block, replace with padding\n");
1947*600f14f4SXin Li if(0 == (padding = new FLAC::Metadata::Padding()))
1948*600f14f4SXin Li return die_("creating PADDING block");
1949*600f14f4SXin Li padding->set_length(71);
1950*600f14f4SXin Li if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1951*600f14f4SXin Li return die_("copying object");
1952*600f14f4SXin Li if(!iterator.delete_block(/*replace_with_padding=*/true))
1953*600f14f4SXin Li return die_c_("iterator.delete_block(true)", chain.status());
1954*600f14f4SXin Li
1955*600f14f4SXin Li block = iterator.get_block();
1956*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1957*600f14f4SXin Li return false;
1958*600f14f4SXin Li delete block;
1959*600f14f4SXin Li
1960*600f14f4SXin Li printf("S[V]PP\tnext\n");
1961*600f14f4SXin Li if(!iterator.next())
1962*600f14f4SXin Li return die_("iterator ended early\n");
1963*600f14f4SXin Li our_current_position++;
1964*600f14f4SXin Li
1965*600f14f4SXin Li printf("SV[P]P\tdelete middle block, don't replace with padding\n");
1966*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
1967*600f14f4SXin Li if(!iterator.delete_block(/*replace_with_padding=*/false))
1968*600f14f4SXin Li return die_c_("iterator.delete_block(false)", chain.status());
1969*600f14f4SXin Li
1970*600f14f4SXin Li block = iterator.get_block();
1971*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1972*600f14f4SXin Li return false;
1973*600f14f4SXin Li delete block;
1974*600f14f4SXin Li
1975*600f14f4SXin Li printf("S[V]P\tnext\n");
1976*600f14f4SXin Li if(!iterator.next())
1977*600f14f4SXin Li return die_("iterator ended early\n");
1978*600f14f4SXin Li our_current_position++;
1979*600f14f4SXin Li
1980*600f14f4SXin Li printf("SV[P]\tdelete last block, replace with padding\n");
1981*600f14f4SXin Li if(0 == (padding = new FLAC::Metadata::Padding()))
1982*600f14f4SXin Li return die_("creating PADDING block");
1983*600f14f4SXin Li padding->set_length(219);
1984*600f14f4SXin Li if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
1985*600f14f4SXin Li return die_("copying object");
1986*600f14f4SXin Li if(!iterator.delete_block(/*replace_with_padding=*/true))
1987*600f14f4SXin Li return die_c_("iterator.delete_block(true)", chain.status());
1988*600f14f4SXin Li
1989*600f14f4SXin Li block = iterator.get_block();
1990*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
1991*600f14f4SXin Li return false;
1992*600f14f4SXin Li delete block;
1993*600f14f4SXin Li
1994*600f14f4SXin Li printf("S[V]P\tnext\n");
1995*600f14f4SXin Li if(!iterator.next())
1996*600f14f4SXin Li return die_("iterator ended early\n");
1997*600f14f4SXin Li our_current_position++;
1998*600f14f4SXin Li
1999*600f14f4SXin Li printf("SV[P]\tdelete last block, don't replace with padding\n");
2000*600f14f4SXin Li delete_from_our_metadata_(our_current_position--);
2001*600f14f4SXin Li if(!iterator.delete_block(/*replace_with_padding=*/false))
2002*600f14f4SXin Li return die_c_("iterator.delete_block(false)", chain.status());
2003*600f14f4SXin Li
2004*600f14f4SXin Li block = iterator.get_block();
2005*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
2006*600f14f4SXin Li return false;
2007*600f14f4SXin Li delete block;
2008*600f14f4SXin Li
2009*600f14f4SXin Li printf("S[V]\tprev\n");
2010*600f14f4SXin Li if(!iterator.prev())
2011*600f14f4SXin Li return die_("iterator ended early\n");
2012*600f14f4SXin Li our_current_position--;
2013*600f14f4SXin Li
2014*600f14f4SXin Li printf("[S]V\tdelete STREAMINFO block, should fail\n");
2015*600f14f4SXin Li if(iterator.delete_block(/*replace_with_padding=*/false))
2016*600f14f4SXin Li return die_("iterator.delete_block() on STREAMINFO should have failed but didn't");
2017*600f14f4SXin Li
2018*600f14f4SXin Li block = iterator.get_block();
2019*600f14f4SXin Li if(!compare_chain_(chain, our_current_position, block))
2020*600f14f4SXin Li return false;
2021*600f14f4SXin Li delete block;
2022*600f14f4SXin Li
2023*600f14f4SXin Li } // delete iterator
2024*600f14f4SXin Li our_current_position = 0;
2025*600f14f4SXin Li
2026*600f14f4SXin Li printf("SV\tmerge padding\n");
2027*600f14f4SXin Li chain.merge_padding();
2028*600f14f4SXin Li
2029*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
2030*600f14f4SXin Li return die_c_("during chain.write(false, false)", chain.status());
2031*600f14f4SXin Li if(!compare_chain_(chain, 0, 0))
2032*600f14f4SXin Li return false;
2033*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
2034*600f14f4SXin Li return false;
2035*600f14f4SXin Li
2036*600f14f4SXin Li printf("SV\tsort padding\n");
2037*600f14f4SXin Li chain.sort_padding();
2038*600f14f4SXin Li
2039*600f14f4SXin Li if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfilename(is_ogg)))
2040*600f14f4SXin Li return die_c_("during chain.write(false, false)", chain.status());
2041*600f14f4SXin Li if(!compare_chain_(chain, 0, 0))
2042*600f14f4SXin Li return false;
2043*600f14f4SXin Li if(!test_file_(is_ogg, /*ignore_metadata=*/false))
2044*600f14f4SXin Li return false;
2045*600f14f4SXin Li
2046*600f14f4SXin Li end:
2047*600f14f4SXin Li if(!remove_file_(flacfilename(is_ogg)))
2048*600f14f4SXin Li return false;
2049*600f14f4SXin Li
2050*600f14f4SXin Li return true;
2051*600f14f4SXin Li }
2052*600f14f4SXin Li
test_level_2_misc_(bool is_ogg)2053*600f14f4SXin Li static bool test_level_2_misc_(bool is_ogg)
2054*600f14f4SXin Li {
2055*600f14f4SXin Li ::FLAC__IOCallbacks callbacks;
2056*600f14f4SXin Li
2057*600f14f4SXin Li memset(&callbacks, 0, sizeof(callbacks));
2058*600f14f4SXin Li callbacks.read = (::FLAC__IOCallback_Read)fread;
2059*600f14f4SXin Li #ifdef FLAC__VALGRIND_TESTING
2060*600f14f4SXin Li callbacks.write = chain_write_cb_;
2061*600f14f4SXin Li #else
2062*600f14f4SXin Li callbacks.write = (::FLAC__IOCallback_Write)fwrite;
2063*600f14f4SXin Li #endif
2064*600f14f4SXin Li callbacks.seek = chain_seek_cb_;
2065*600f14f4SXin Li callbacks.tell = chain_tell_cb_;
2066*600f14f4SXin Li callbacks.eof = chain_eof_cb_;
2067*600f14f4SXin Li
2068*600f14f4SXin Li printf("\n\n++++++ testing level 2 interface (mismatched read/write protections)\n");
2069*600f14f4SXin Li
2070*600f14f4SXin Li printf("generate file\n");
2071*600f14f4SXin Li
2072*600f14f4SXin Li if(!generate_file_(/*include_extras=*/false, is_ogg))
2073*600f14f4SXin Li return false;
2074*600f14f4SXin Li
2075*600f14f4SXin Li printf("create chain\n");
2076*600f14f4SXin Li FLAC::Metadata::Chain chain;
2077*600f14f4SXin Li if(!chain.is_valid())
2078*600f14f4SXin Li return die_("allocating chain");
2079*600f14f4SXin Li
2080*600f14f4SXin Li printf("read chain (filename-based)\n");
2081*600f14f4SXin Li
2082*600f14f4SXin Li if(!chain.read(flacfilename(is_ogg)))
2083*600f14f4SXin Li return die_c_("reading chain", chain.status());
2084*600f14f4SXin Li
2085*600f14f4SXin Li printf("write chain with wrong method Chain::write(with callbacks)\n");
2086*600f14f4SXin Li {
2087*600f14f4SXin Li if(chain.write(/*use_padding=*/false, 0, callbacks))
2088*600f14f4SXin Li return die_c_("mismatched write should have failed", chain.status());
2089*600f14f4SXin Li if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2090*600f14f4SXin Li return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
2091*600f14f4SXin Li printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2092*600f14f4SXin Li }
2093*600f14f4SXin Li
2094*600f14f4SXin Li printf("read chain (filename-based)\n");
2095*600f14f4SXin Li
2096*600f14f4SXin Li if(!chain.read(flacfilename(is_ogg)))
2097*600f14f4SXin Li return die_c_("reading chain", chain.status());
2098*600f14f4SXin Li
2099*600f14f4SXin Li printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
2100*600f14f4SXin Li {
2101*600f14f4SXin Li if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
2102*600f14f4SXin Li return die_c_("mismatched write should have failed", chain.status());
2103*600f14f4SXin Li if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2104*600f14f4SXin Li return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
2105*600f14f4SXin Li printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2106*600f14f4SXin Li }
2107*600f14f4SXin Li
2108*600f14f4SXin Li printf("read chain (callback-based)\n");
2109*600f14f4SXin Li {
2110*600f14f4SXin Li FILE *file = flac_fopen(flacfilename(is_ogg), "rb");
2111*600f14f4SXin Li if(0 == file)
2112*600f14f4SXin Li return die_("opening file");
2113*600f14f4SXin Li if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
2114*600f14f4SXin Li fclose(file);
2115*600f14f4SXin Li return die_c_("reading chain", chain.status());
2116*600f14f4SXin Li }
2117*600f14f4SXin Li fclose(file);
2118*600f14f4SXin Li }
2119*600f14f4SXin Li
2120*600f14f4SXin Li printf("write chain with wrong method write()\n");
2121*600f14f4SXin Li {
2122*600f14f4SXin Li if(chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false))
2123*600f14f4SXin Li return die_c_("mismatched write should have failed", chain.status());
2124*600f14f4SXin Li if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
2125*600f14f4SXin Li return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
2126*600f14f4SXin Li printf(" OK: write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it should\n");
2127*600f14f4SXin Li }
2128*600f14f4SXin Li
2129*600f14f4SXin Li printf("read chain (callback-based)\n");
2130*600f14f4SXin Li {
2131*600f14f4SXin Li FILE *file = flac_fopen(flacfilename(is_ogg), "rb");
2132*600f14f4SXin Li if(0 == file)
2133*600f14f4SXin Li return die_("opening file");
2134*600f14f4SXin Li if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
2135*600f14f4SXin Li fclose(file);
2136*600f14f4SXin Li return die_c_("reading chain", chain.status());
2137*600f14f4SXin Li }
2138*600f14f4SXin Li fclose(file);
2139*600f14f4SXin Li }
2140*600f14f4SXin Li
2141*600f14f4SXin Li printf("testing Chain::check_if_tempfile_needed()... ");
2142*600f14f4SXin Li
2143*600f14f4SXin Li if(!chain.check_if_tempfile_needed(/*use_padding=*/false))
2144*600f14f4SXin Li printf("OK: Chain::check_if_tempfile_needed() returned false like it should\n");
2145*600f14f4SXin Li else
2146*600f14f4SXin Li return die_("Chain::check_if_tempfile_needed() returned true but shouldn't have");
2147*600f14f4SXin Li
2148*600f14f4SXin Li printf("write chain with wrong method Chain::write(with callbacks and tempfile)\n");
2149*600f14f4SXin Li {
2150*600f14f4SXin Li if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
2151*600f14f4SXin Li return die_c_("mismatched write should have failed", chain.status());
2152*600f14f4SXin Li if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2153*600f14f4SXin Li return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
2154*600f14f4SXin Li printf(" OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2155*600f14f4SXin Li }
2156*600f14f4SXin Li
2157*600f14f4SXin Li printf("read chain (callback-based)\n");
2158*600f14f4SXin Li {
2159*600f14f4SXin Li FILE *file = flac_fopen(flacfilename(is_ogg), "rb");
2160*600f14f4SXin Li if(0 == file)
2161*600f14f4SXin Li return die_("opening file");
2162*600f14f4SXin Li if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
2163*600f14f4SXin Li fclose(file);
2164*600f14f4SXin Li return die_c_("reading chain", chain.status());
2165*600f14f4SXin Li }
2166*600f14f4SXin Li fclose(file);
2167*600f14f4SXin Li }
2168*600f14f4SXin Li
2169*600f14f4SXin Li printf("create iterator\n");
2170*600f14f4SXin Li {
2171*600f14f4SXin Li FLAC::Metadata::Iterator iterator;
2172*600f14f4SXin Li if(!iterator.is_valid())
2173*600f14f4SXin Li return die_("allocating memory for iterator");
2174*600f14f4SXin Li
2175*600f14f4SXin Li iterator.init(chain);
2176*600f14f4SXin Li
2177*600f14f4SXin Li printf("[S]VP\tnext\n");
2178*600f14f4SXin Li if(!iterator.next())
2179*600f14f4SXin Li return die_("iterator ended early\n");
2180*600f14f4SXin Li
2181*600f14f4SXin Li printf("S[V]P\tdelete VORBIS_COMMENT, write\n");
2182*600f14f4SXin Li if(!iterator.delete_block(/*replace_with_padding=*/false))
2183*600f14f4SXin Li return die_c_("block delete failed\n", chain.status());
2184*600f14f4SXin Li
2185*600f14f4SXin Li printf("testing Chain::check_if_tempfile_needed()... ");
2186*600f14f4SXin Li
2187*600f14f4SXin Li if(chain.check_if_tempfile_needed(/*use_padding=*/false))
2188*600f14f4SXin Li printf("OK: Chain::check_if_tempfile_needed() returned true like it should\n");
2189*600f14f4SXin Li else
2190*600f14f4SXin Li return die_("Chain::check_if_tempfile_needed() returned false but shouldn't have");
2191*600f14f4SXin Li
2192*600f14f4SXin Li printf("write chain with wrong method Chain::write(with callbacks)\n");
2193*600f14f4SXin Li {
2194*600f14f4SXin Li if(chain.write(/*use_padding=*/false, 0, callbacks))
2195*600f14f4SXin Li return die_c_("mismatched write should have failed", chain.status());
2196*600f14f4SXin Li if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
2197*600f14f4SXin Li return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
2198*600f14f4SXin Li printf(" OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it should\n");
2199*600f14f4SXin Li }
2200*600f14f4SXin Li
2201*600f14f4SXin Li } // delete iterator
2202*600f14f4SXin Li
2203*600f14f4SXin Li if(!remove_file_(flacfilename(is_ogg)))
2204*600f14f4SXin Li return false;
2205*600f14f4SXin Li
2206*600f14f4SXin Li return true;
2207*600f14f4SXin Li }
2208*600f14f4SXin Li
test_metadata_file_manipulation()2209*600f14f4SXin Li bool test_metadata_file_manipulation()
2210*600f14f4SXin Li {
2211*600f14f4SXin Li printf("\n+++ libFLAC++ unit test: metadata manipulation\n\n");
2212*600f14f4SXin Li
2213*600f14f4SXin Li our_metadata_.num_blocks = 0;
2214*600f14f4SXin Li
2215*600f14f4SXin Li if(!test_level_0_())
2216*600f14f4SXin Li return false;
2217*600f14f4SXin Li
2218*600f14f4SXin Li if(!test_level_1_())
2219*600f14f4SXin Li return false;
2220*600f14f4SXin Li
2221*600f14f4SXin Li if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/false)) /* filename-based */
2222*600f14f4SXin Li return false;
2223*600f14f4SXin Li if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/false)) /* callback-based */
2224*600f14f4SXin Li return false;
2225*600f14f4SXin Li if(!test_level_2_misc_(/*is_ogg=*/false))
2226*600f14f4SXin Li return false;
2227*600f14f4SXin Li
2228*600f14f4SXin Li if(FLAC_API_SUPPORTS_OGG_FLAC) {
2229*600f14f4SXin Li if(!test_level_2_(/*filename_based=*/true, /*is_ogg=*/true)) /* filename-based */
2230*600f14f4SXin Li return false;
2231*600f14f4SXin Li if(!test_level_2_(/*filename_based=*/false, /*is_ogg=*/true)) /* callback-based */
2232*600f14f4SXin Li return false;
2233*600f14f4SXin Li #if 0
2234*600f14f4SXin Li /* when ogg flac write is supported, will have to add this: */
2235*600f14f4SXin Li if(!test_level_2_misc_(/*is_ogg=*/true))
2236*600f14f4SXin Li return false;
2237*600f14f4SXin Li #endif
2238*600f14f4SXin Li }
2239*600f14f4SXin Li
2240*600f14f4SXin Li return true;
2241*600f14f4SXin Li }
2242