metadata_manip.cpp
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:67k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* test_libFLAC++ - Unit tester for libFLAC++
  2.  * Copyright (C) 2002,2003,2004,2005  Josh Coalson
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. extern "C" {
  19. #include "file_utils.h"
  20. }
  21. #include "FLAC/assert.h"
  22. #include "FLAC++/decoder.h"
  23. #include "FLAC++/metadata.h"
  24. #include "share/grabbag.h"
  25. #include <stdio.h>
  26. #include <stdlib.h> /* for malloc() */
  27. #include <string.h> /* for memcpy()/memset() */
  28. #if defined _MSC_VER || defined __MINGW32__
  29. #include <sys/utime.h> /* for utime() */
  30. #include <io.h> /* for chmod() */
  31. #else
  32. #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
  33. #include <utime.h> /* for utime() */
  34. #include <unistd.h> /* for chown(), unlink() */
  35. #endif
  36. #include <sys/stat.h> /* for stat(), maybe chmod() */
  37. /******************************************************************************
  38. The general strategy of these tests (for interface levels 1 and 2) is
  39. to create a dummy FLAC file with a known set of initial metadata
  40. blocks, then keep a mirror locally of what we expect the metadata to be
  41. after each operation.  Then testing becomes a simple matter of running
  42. a FLAC::Decoder::File over the dummy file after each operation, comparing
  43. the decoded metadata to what's in our local copy.  If there are any
  44. differences in the metadata, or the actual audio data is corrupted, we
  45. will catch it while decoding.
  46. ******************************************************************************/
  47. class OurFileDecoder: public FLAC::Decoder::File {
  48. public:
  49. inline OurFileDecoder(bool ignore_metadata): ignore_metadata_(ignore_metadata), error_occurred_(false) { }
  50. bool ignore_metadata_;
  51. bool error_occurred_;
  52. protected:
  53. ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
  54. void metadata_callback(const ::FLAC__StreamMetadata *metadata);
  55. void error_callback(::FLAC__StreamDecoderErrorStatus status);
  56. };
  57. struct OurMetadata {
  58. FLAC::Metadata::Prototype *blocks[64];
  59. unsigned num_blocks;
  60. };
  61. static const char *flacfile_ = "metadata.flac";
  62. /* our copy of the metadata in flacfile_ */
  63. static OurMetadata our_metadata_;
  64. /* the current block number that corresponds to the position of the iterator we are testing */
  65. static unsigned mc_our_block_number_ = 0;
  66. static bool die_(const char *msg)
  67. {
  68. printf("ERROR: %sn", msg);
  69. return false;
  70. }
  71. static bool die_c_(const char *msg, FLAC::Metadata::Chain::Status status)
  72. {
  73. printf("ERROR: %sn", msg);
  74. printf("       status=%u (%s)n", (unsigned)((::FLAC__Metadata_ChainStatus)status), status.as_cstring());
  75. return false;
  76. }
  77. static bool die_ss_(const char *msg, FLAC::Metadata::SimpleIterator &iterator)
  78. {
  79. const FLAC::Metadata::SimpleIterator::Status status = iterator.status();
  80. printf("ERROR: %sn", msg);
  81. printf("       status=%u (%s)n", (unsigned)((::FLAC__Metadata_SimpleIteratorStatus)status), status.as_cstring());
  82. return false;
  83. }
  84. static void *malloc_or_die_(size_t size)
  85. {
  86. void *x = malloc(size);
  87. if(0 == x) {
  88. fprintf(stderr, "ERROR: out of memory allocating %u bytesn", (unsigned)size);
  89. exit(1);
  90. }
  91. return x;
  92. }
  93. /* functions for working with our metadata copy */
  94. static bool replace_in_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
  95. {
  96. unsigned i;
  97. FLAC::Metadata::Prototype *obj = block;
  98. FLAC__ASSERT(position < our_metadata_.num_blocks);
  99. if(copy) {
  100. if(0 == (obj = FLAC::Metadata::clone(block)))
  101. return die_("during FLAC::Metadata::clone()");
  102. }
  103. delete our_metadata_.blocks[position];
  104. our_metadata_.blocks[position] = obj;
  105. /* set the is_last flags */
  106. for(i = 0; i < our_metadata_.num_blocks - 1; i++)
  107. our_metadata_.blocks[i]->set_is_last(false);
  108. our_metadata_.blocks[i]->set_is_last(true);
  109. return true;
  110. }
  111. static bool insert_to_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
  112. {
  113. unsigned i;
  114. FLAC::Metadata::Prototype *obj = block;
  115. if(copy) {
  116. if(0 == (obj = FLAC::Metadata::clone(block)))
  117. return die_("during FLAC::Metadata::clone()");
  118. }
  119. if(position > our_metadata_.num_blocks) {
  120. position = our_metadata_.num_blocks;
  121. }
  122. else {
  123. for(i = our_metadata_.num_blocks; i > position; i--)
  124. our_metadata_.blocks[i] = our_metadata_.blocks[i-1];
  125. }
  126. our_metadata_.blocks[position] = obj;
  127. our_metadata_.num_blocks++;
  128. /* set the is_last flags */
  129. for(i = 0; i < our_metadata_.num_blocks - 1; i++)
  130. our_metadata_.blocks[i]->set_is_last(false);
  131. our_metadata_.blocks[i]->set_is_last(true);
  132. return true;
  133. }
  134. static void delete_from_our_metadata_(unsigned position)
  135. {
  136. unsigned i;
  137. FLAC__ASSERT(position < our_metadata_.num_blocks);
  138. delete our_metadata_.blocks[position];
  139. for(i = position; i < our_metadata_.num_blocks - 1; i++)
  140. our_metadata_.blocks[i] = our_metadata_.blocks[i+1];
  141. our_metadata_.num_blocks--;
  142. /* set the is_last flags */
  143. if(our_metadata_.num_blocks > 0) {
  144. for(i = 0; i < our_metadata_.num_blocks - 1; i++)
  145. our_metadata_.blocks[i]->set_is_last(false);
  146. our_metadata_.blocks[i]->set_is_last(true);
  147. }
  148. }
  149. void add_to_padding_length_(unsigned index, int delta)
  150. {
  151. FLAC::Metadata::Padding *padding = dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[index]);
  152. FLAC__ASSERT(0 != padding);
  153. padding->set_length((unsigned)((int)padding->get_length() + delta));
  154. }
  155. /*
  156.  * This wad of functions supports filename- and callback-based chain reading/writing.
  157.  * Everything up to set_file_stats_() is copied from libFLAC/metadata_iterators.c
  158.  */
  159. bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
  160. {
  161. static const char *tempfile_suffix = ".metadata_edit";
  162. if(0 == (*tempfilename = (char*)malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
  163. return false;
  164. strcpy(*tempfilename, filename);
  165. strcat(*tempfilename, tempfile_suffix);
  166. if(0 == (*tempfile = fopen(*tempfilename, "wb")))
  167. return false;
  168. return true;
  169. }
  170. void cleanup_tempfile_(FILE **tempfile, char **tempfilename)
  171. {
  172. if(0 != *tempfile) {
  173. (void)fclose(*tempfile);
  174. *tempfile = 0;
  175. }
  176. if(0 != *tempfilename) {
  177. (void)unlink(*tempfilename);
  178. free(*tempfilename);
  179. *tempfilename = 0;
  180. }
  181. }
  182. bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
  183. {
  184. FLAC__ASSERT(0 != filename);
  185. FLAC__ASSERT(0 != tempfile);
  186. FLAC__ASSERT(0 != tempfilename);
  187. FLAC__ASSERT(0 != *tempfilename);
  188. if(0 != *tempfile) {
  189. (void)fclose(*tempfile);
  190. *tempfile = 0;
  191. }
  192. #if defined _MSC_VER || defined __MINGW32__
  193. if(unlink(filename) < 0) {
  194. cleanup_tempfile_(tempfile, tempfilename);
  195. return false;
  196. }
  197. #endif
  198. if(0 != rename(*tempfilename, filename)) {
  199. cleanup_tempfile_(tempfile, tempfilename);
  200. return false;
  201. }
  202. cleanup_tempfile_(tempfile, tempfilename);
  203. return true;
  204. }
  205. bool get_file_stats_(const char *filename, struct stat *stats)
  206. {
  207. FLAC__ASSERT(0 != filename);
  208. FLAC__ASSERT(0 != stats);
  209. return (0 == stat(filename, stats));
  210. }
  211. void set_file_stats_(const char *filename, struct stat *stats)
  212. {
  213. struct utimbuf srctime;
  214. FLAC__ASSERT(0 != filename);
  215. FLAC__ASSERT(0 != stats);
  216. srctime.actime = stats->st_atime;
  217. srctime.modtime = stats->st_mtime;
  218. (void)chmod(filename, stats->st_mode);
  219. (void)utime(filename, &srctime);
  220. #if !defined _MSC_VER && !defined __MINGW32__
  221. (void)chown(filename, stats->st_uid, (gid_t)(-1));
  222. (void)chown(filename, (uid_t)(-1), stats->st_gid);
  223. #endif
  224. }
  225. #ifdef FLAC__VALGRIND_TESTING
  226. static size_t chain_write_cb_(const void *ptr, size_t size, size_t nmemb, ::FLAC__IOHandle handle)
  227. {
  228. FILE *stream = (FILE*)handle;
  229. size_t ret = fwrite(ptr, size, nmemb, stream);
  230. if(!ferror(stream))
  231. fflush(stream);
  232. return ret;
  233. }
  234. #endif
  235. static int chain_seek_cb_(::FLAC__IOHandle handle, FLAC__int64 offset, int whence)
  236. {
  237. long o = (long)offset;
  238. FLAC__ASSERT(offset == o);
  239. return fseek((FILE*)handle, o, whence);
  240. }
  241. static FLAC__int64 chain_tell_cb_(::FLAC__IOHandle handle)
  242. {
  243. return ftell((FILE*)handle);
  244. }
  245. static int chain_eof_cb_(::FLAC__IOHandle handle)
  246. {
  247. return feof((FILE*)handle);
  248. }
  249. static bool write_chain_(FLAC::Metadata::Chain &chain, bool use_padding, bool preserve_file_stats, bool filename_based, const char *filename)
  250. {
  251. if(filename_based)
  252. return chain.write(use_padding, preserve_file_stats);
  253. else {
  254. ::FLAC__IOCallbacks callbacks;
  255. memset(&callbacks, 0, sizeof(callbacks));
  256. callbacks.read = (::FLAC__IOCallback_Read)fread;
  257. #ifdef FLAC__VALGRIND_TESTING
  258. callbacks.write = chain_write_cb_;
  259. #else
  260. callbacks.write = (::FLAC__IOCallback_Write)fwrite;
  261. #endif
  262. callbacks.seek = chain_seek_cb_;
  263. callbacks.eof = chain_eof_cb_;
  264. if(chain.check_if_tempfile_needed(use_padding)) {
  265. struct stat stats;
  266. FILE *file, *tempfile;
  267. char *tempfilename;
  268. if(preserve_file_stats) {
  269. if(!get_file_stats_(filename, &stats))
  270. return false;
  271. }
  272. if(0 == (file = fopen(filename, "rb")))
  273. return false; /*@@@ chain status still says OK though */
  274. if(!open_tempfile_(filename, &tempfile, &tempfilename)) {
  275. fclose(file);
  276. cleanup_tempfile_(&tempfile, &tempfilename);
  277. return false; /*@@@ chain status still says OK though */
  278. }
  279. if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks, (::FLAC__IOHandle)tempfile, callbacks)) {
  280. fclose(file);
  281. fclose(tempfile);
  282. return false;
  283. }
  284. fclose(file);
  285. fclose(tempfile);
  286. file = tempfile = 0;
  287. if(!transport_tempfile_(filename, &tempfile, &tempfilename))
  288. return false;
  289. if(preserve_file_stats)
  290. set_file_stats_(filename, &stats);
  291. }
  292. else {
  293. FILE *file = fopen(filename, "r+b");
  294. if(0 == file)
  295. return false; /*@@@ chain status still says OK though */
  296. if(!chain.write(use_padding, (::FLAC__IOHandle)file, callbacks))
  297. return false;
  298. fclose(file);
  299. }
  300. }
  301. return true;
  302. }
  303. static bool read_chain_(FLAC::Metadata::Chain &chain, const char *filename, bool filename_based)
  304. {
  305. if(filename_based)
  306. return chain.read(filename);
  307. else {
  308. ::FLAC__IOCallbacks callbacks;
  309. memset(&callbacks, 0, sizeof(callbacks));
  310. callbacks.read = (::FLAC__IOCallback_Read)fread;
  311. callbacks.seek = chain_seek_cb_;
  312. callbacks.tell = chain_tell_cb_;
  313. {
  314. bool ret;
  315. FILE *file = fopen(filename, "rb");
  316. if(0 == file)
  317. return false; /*@@@ chain status still says OK though */
  318. ret = chain.read((::FLAC__IOHandle)file, callbacks);
  319. fclose(file);
  320. return ret;
  321. }
  322. }
  323. }
  324. /* function for comparing our metadata to a FLAC::Metadata::Chain */
  325. static bool compare_chain_(FLAC::Metadata::Chain &chain, unsigned current_position, FLAC::Metadata::Prototype *current_block)
  326. {
  327. unsigned i;
  328. FLAC::Metadata::Iterator iterator;
  329. bool next_ok = true;
  330. printf("tcomparing chain... ");
  331. fflush(stdout);
  332. if(!iterator.is_valid())
  333. return die_("allocating memory for iterator");
  334. iterator.init(chain);
  335. i = 0;
  336. do {
  337. FLAC::Metadata::Prototype *block;
  338. printf("%u... ", i);
  339. fflush(stdout);
  340. if(0 == (block = iterator.get_block()))
  341. return die_("getting block from iterator");
  342. if(*block != *our_metadata_.blocks[i])
  343. return die_("metadata block mismatch");
  344. delete block;
  345. i++;
  346. next_ok = iterator.next();
  347. } while(i < our_metadata_.num_blocks && next_ok);
  348. if(next_ok)
  349. return die_("chain has more blocks than expected");
  350. if(i < our_metadata_.num_blocks)
  351. return die_("short block count in chain");
  352. if(0 != current_block) {
  353. printf("CURRENT_POSITION... ");
  354. fflush(stdout);
  355. if(*current_block != *our_metadata_.blocks[current_position])
  356. return die_("metadata block mismatch");
  357. }
  358. printf("PASSEDn");
  359. return true;
  360. }
  361. ::FLAC__StreamDecoderWriteStatus OurFileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
  362. {
  363. (void)buffer;
  364. if(
  365. (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
  366. (frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
  367. ) {
  368. printf("content... ");
  369. fflush(stdout);
  370. }
  371. return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
  372. }
  373. void OurFileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
  374. {
  375. /* don't bother checking if we've already hit an error */
  376. if(error_occurred_)
  377. return;
  378. printf("%d... ", mc_our_block_number_);
  379. fflush(stdout);
  380. if(!ignore_metadata_) {
  381. if(mc_our_block_number_ >= our_metadata_.num_blocks) {
  382. (void)die_("got more metadata blocks than expected");
  383. error_occurred_ = true;
  384. }
  385. else {
  386. if(*our_metadata_.blocks[mc_our_block_number_] != metadata) {
  387. (void)die_("metadata block mismatch");
  388. error_occurred_ = true;
  389. }
  390. }
  391. }
  392. mc_our_block_number_++;
  393. }
  394. void OurFileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
  395. {
  396. error_occurred_ = true;
  397. printf("ERROR: got error callback, status = %s (%u)n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
  398. }
  399. static bool generate_file_()
  400. {
  401. ::FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
  402. ::FLAC__StreamMetadata *metadata[1];
  403. printf("generating FLAC file for testn");
  404. while(our_metadata_.num_blocks > 0)
  405. delete_from_our_metadata_(0);
  406. streaminfo.is_last = false;
  407. streaminfo.type = ::FLAC__METADATA_TYPE_STREAMINFO;
  408. streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
  409. streaminfo.data.stream_info.min_blocksize = 576;
  410. streaminfo.data.stream_info.max_blocksize = 576;
  411. streaminfo.data.stream_info.min_framesize = 0;
  412. streaminfo.data.stream_info.max_framesize = 0;
  413. streaminfo.data.stream_info.sample_rate = 44100;
  414. streaminfo.data.stream_info.channels = 1;
  415. streaminfo.data.stream_info.bits_per_sample = 8;
  416. streaminfo.data.stream_info.total_samples = 0;
  417. memset(streaminfo.data.stream_info.md5sum, 0, 16);
  418. {
  419. const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
  420. vorbiscomment.is_last = false;
  421. vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
  422. vorbiscomment.length = (4 + vendor_string_length) + 4;
  423. vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
  424. vorbiscomment.data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
  425. memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
  426. vorbiscomment.data.vorbis_comment.num_comments = 0;
  427. vorbiscomment.data.vorbis_comment.comments = 0;
  428. }
  429. padding.is_last = true;
  430. padding.type = ::FLAC__METADATA_TYPE_PADDING;
  431. padding.length = 1234;
  432. metadata[0] = &padding;
  433. FLAC::Metadata::StreamInfo s(&streaminfo);
  434. FLAC::Metadata::VorbisComment v(&vorbiscomment);
  435. FLAC::Metadata::Padding p(&padding);
  436. if(
  437. !insert_to_our_metadata_(&s, 0, /*copy=*/true) ||
  438. !insert_to_our_metadata_(&v, 1, /*copy=*/true) ||
  439. !insert_to_our_metadata_(&p, 2, /*copy=*/true)
  440. )
  441. return die_("priming our metadata");
  442. if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
  443. return die_("creating the encoded file");
  444. free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
  445. return true;
  446. }
  447. static bool test_file_(const char *filename, bool ignore_metadata)
  448. {
  449. OurFileDecoder decoder(ignore_metadata);
  450. FLAC__ASSERT(0 != filename);
  451. mc_our_block_number_ = 0;
  452. decoder.error_occurred_ = false;
  453. printf("ttesting '%s'... ", filename);
  454. fflush(stdout);
  455. if(!decoder.is_valid())
  456. return die_("couldn't allocate decoder instance");
  457. decoder.set_md5_checking(true);
  458. decoder.set_filename(filename);
  459. decoder.set_metadata_respond_all();
  460. if(decoder.init() != ::FLAC__FILE_DECODER_OK) {
  461. decoder.finish();
  462. return die_("initializing decodern");
  463. }
  464. if(!decoder.process_until_end_of_file()) {
  465. decoder.finish();
  466. return die_("decoding filen");
  467. }
  468. decoder.finish();
  469. if(decoder.error_occurred_)
  470. return false;
  471. if(mc_our_block_number_ != our_metadata_.num_blocks)
  472. return die_("short metadata block count");
  473. printf("PASSEDn");
  474. return true;
  475. }
  476. static bool change_stats_(const char *filename, bool read_only)
  477. {
  478. if(!grabbag__file_change_stats(filename, read_only))
  479. return die_("during grabbag__file_change_stats()");
  480. return true;
  481. }
  482. static bool remove_file_(const char *filename)
  483. {
  484. while(our_metadata_.num_blocks > 0)
  485. delete_from_our_metadata_(0);
  486. if(!grabbag__file_remove_file(filename))
  487. return die_("removing file");
  488. return true;
  489. }
  490. static bool test_level_0_()
  491. {
  492. FLAC::Metadata::StreamInfo streaminfo;
  493. printf("nn++++++ testing level 0 interfacen");
  494. if(!generate_file_())
  495. return false;
  496. if(!test_file_(flacfile_, /*ignore_metadata=*/true))
  497. return false;
  498. printf("testing FLAC::Metadata::get_streaminfo()... ");
  499. if(!FLAC::Metadata::get_streaminfo(flacfile_, streaminfo))
  500. return die_("during FLAC::Metadata::get_streaminfo()");
  501. /* check to see if some basic data matches (c.f. generate_file_()) */
  502. if(streaminfo.get_channels() != 1)
  503. return die_("mismatch in streaminfo.get_channels()");
  504. if(streaminfo.get_bits_per_sample() != 8)
  505. return die_("mismatch in streaminfo.get_bits_per_sample()");
  506. if(streaminfo.get_sample_rate() != 44100)
  507. return die_("mismatch in streaminfo.get_sample_rate()");
  508. if(streaminfo.get_min_blocksize() != 576)
  509. return die_("mismatch in streaminfo.get_min_blocksize()");
  510. if(streaminfo.get_max_blocksize() != 576)
  511. return die_("mismatch in streaminfo.get_max_blocksize()");
  512. printf("OKn");
  513. {
  514. printf("testing FLAC::Metadata::get_tags(VorbisComment *&)... ");
  515. FLAC::Metadata::VorbisComment *tags = 0;
  516. if(!FLAC::Metadata::get_tags(flacfile_, tags))
  517. return die_("during FLAC::Metadata::get_tags()");
  518. /* check to see if some basic data matches (c.f. generate_file_()) */
  519. if(tags->get_num_comments() != 0)
  520. return die_("mismatch in tags->get_num_comments()");
  521. printf("OKn");
  522. delete tags;
  523. }
  524. {
  525. printf("testing FLAC::Metadata::get_tags(VorbisComment &)... ");
  526. FLAC::Metadata::VorbisComment tags;
  527. if(!FLAC::Metadata::get_tags(flacfile_, tags))
  528. return die_("during FLAC::Metadata::get_tags()");
  529. /* check to see if some basic data matches (c.f. generate_file_()) */
  530. if(tags.get_num_comments() != 0)
  531. return die_("mismatch in tags.get_num_comments()");
  532. printf("OKn");
  533. }
  534. if(!remove_file_(flacfile_))
  535. return false;
  536. return true;
  537. }
  538. static bool test_level_1_()
  539. {
  540. FLAC::Metadata::Prototype *block;
  541. FLAC::Metadata::StreamInfo *streaminfo;
  542. FLAC::Metadata::Padding *padding;
  543. FLAC::Metadata::Application *app;
  544. FLAC__byte data[1000];
  545. unsigned our_current_position = 0;
  546. // initialize 'data' to avoid Valgrind errors
  547. memset(data, 0, sizeof(data));
  548. printf("nn++++++ testing level 1 interfacen");
  549. /************************************************************/
  550. {
  551. printf("simple iterator on read-only filen");
  552. if(!generate_file_())
  553. return false;
  554. if(!change_stats_(flacfile_, /*read_only=*/true))
  555. return false;
  556. if(!test_file_(flacfile_, /*ignore_metadata=*/true))
  557. return false;
  558. FLAC::Metadata::SimpleIterator iterator;
  559. if(!iterator.is_valid())
  560. return die_("iterator.is_valid() returned false");
  561. if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
  562. return die_("iterator.init() returned false");
  563. printf("is writable = %un", (unsigned)iterator.is_writable());
  564. if(iterator.is_writable())
  565. return die_("iterator claims file is writable when tester thinks it should not be; are you running as root?n");
  566. printf("iterate forwardsn");
  567. if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
  568. return die_("expected STREAMINFO type from iterator.get_block_type()");
  569. if(0 == (block = iterator.get_block()))
  570. return die_("getting block 0");
  571. if(block->get_type() != ::FLAC__METADATA_TYPE_STREAMINFO)
  572. return die_("expected STREAMINFO type");
  573. if(block->get_is_last())
  574. return die_("expected is_last to be false");
  575. if(block->get_length() != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
  576. return die_("bad STREAMINFO length");
  577. /* check to see if some basic data matches (c.f. generate_file_()) */
  578. streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
  579. FLAC__ASSERT(0 != streaminfo);
  580. if(streaminfo->get_channels() != 1)
  581. return die_("mismatch in channels");
  582. if(streaminfo->get_bits_per_sample() != 8)
  583. return die_("mismatch in bits_per_sample");
  584. if(streaminfo->get_sample_rate() != 44100)
  585. return die_("mismatch in sample_rate");
  586. if(streaminfo->get_min_blocksize() != 576)
  587. return die_("mismatch in min_blocksize");
  588. if(streaminfo->get_max_blocksize() != 576)
  589. return die_("mismatch in max_blocksize");
  590. // we will delete streaminfo a little later when we're really done with it...
  591. if(!iterator.next())
  592. return die_("forward iterator ended early");
  593. our_current_position++;
  594. if(!iterator.next())
  595. return die_("forward iterator ended early");
  596. our_current_position++;
  597. if(iterator.get_block_type() != ::FLAC__METADATA_TYPE_PADDING)
  598. return die_("expected PADDING type from iterator.get_block_type()");
  599. if(0 == (block = iterator.get_block()))
  600. return die_("getting block 1");
  601. if(block->get_type() != ::FLAC__METADATA_TYPE_PADDING)
  602. return die_("expected PADDING type");
  603. if(!block->get_is_last())
  604. return die_("expected is_last to be true");
  605. /* check to see if some basic data matches (c.f. generate_file_()) */
  606. if(block->get_length() != 1234)
  607. return die_("bad PADDING length");
  608. delete block;
  609. if(iterator.next())
  610. return die_("forward iterator returned true but should have returned false");
  611. printf("iterate backwardsn");
  612. if(!iterator.prev())
  613. return die_("reverse iterator ended early");
  614. if(!iterator.prev())
  615. return die_("reverse iterator ended early");
  616. if(iterator.prev())
  617. return die_("reverse iterator returned true but should have returned false");
  618. printf("testing iterator.set_block() on read-only file...n");
  619. if(!iterator.set_block(streaminfo, false))
  620. printf("PASSED.  iterator.set_block() returned false like it shouldn");
  621. else
  622. return die_("iterator.set_block() returned true but shouldn't have");
  623. delete streaminfo;
  624. }
  625. /************************************************************/
  626. {
  627. printf("simple iterator on writable filen");
  628. if(!change_stats_(flacfile_, /*read-only=*/false))
  629. return false;
  630. printf("creating APPLICATION blockn");
  631. if(0 == (app = new FLAC::Metadata::Application()))
  632. return die_("new FLAC::Metadata::Application()");
  633. app->set_id((const unsigned char *)"duh");
  634. printf("creating PADDING blockn");
  635. if(0 == (padding = new FLAC::Metadata::Padding()))
  636. return die_("new FLAC::Metadata::Padding()");
  637. padding->set_length(20);
  638. FLAC::Metadata::SimpleIterator iterator;
  639. if(!iterator.is_valid())
  640. return die_("iterator.is_valid() returned false");
  641. if(!iterator.init(flacfile_, /*read_only=*/false, /*preserve_file_stats=*/false))
  642. return die_("iterator.init() returned false");
  643. our_current_position = 0;
  644. printf("is writable = %un", (unsigned)iterator.is_writable());
  645. printf("[S]VPttry to write over STREAMINFO block...n");
  646. if(!iterator.set_block(app, false))
  647. printf("titerator.set_block() returned false like it shouldn");
  648. else
  649. return die_("iterator.set_block() returned true but shouldn't have");
  650. printf("[S]VPtnextn");
  651. if(!iterator.next())
  652. return die_("iterator ended earlyn");
  653. our_current_position++;
  654. printf("S[V]Ptnextn");
  655. if(!iterator.next())
  656. return die_("iterator ended earlyn");
  657. our_current_position++;
  658. printf("SV[P]tinsert PADDING after, don't expand into paddingn");
  659. padding->set_length(25);
  660. if(!iterator.insert_block_after(padding, false))
  661. return die_ss_("iterator.insert_block_after(padding, false)", iterator);
  662. if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
  663. return false;
  664. printf("SVP[P]tprevn");
  665. if(!iterator.prev())
  666. return die_("iterator ended earlyn");
  667. our_current_position--;
  668. printf("SV[P]Ptprevn");
  669. if(!iterator.prev())
  670. return die_("iterator ended earlyn");
  671. our_current_position--;
  672. printf("S[V]PPtinsert PADDING after, don't expand into paddingn");
  673. padding->set_length(30);
  674. if(!iterator.insert_block_after(padding, false))
  675. return die_ss_("iterator.insert_block_after(padding, false)", iterator);
  676. if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
  677. return false;
  678. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  679. return false;
  680. printf("SV[P]PPtprevn");
  681. if(!iterator.prev())
  682. return die_("iterator ended earlyn");
  683. our_current_position--;
  684. printf("S[V]PPPtprevn");
  685. if(!iterator.prev())
  686. return die_("iterator ended earlyn");
  687. our_current_position--;
  688. printf("[S]VPPPtdelete (STREAMINFO block), must failn");
  689. if(iterator.delete_block(false))
  690. return die_ss_("iterator.delete_block(false) should have returned false", iterator);
  691. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  692. return false;
  693. printf("[S]VPPPtnextn");
  694. if(!iterator.next())
  695. return die_("iterator ended earlyn");
  696. our_current_position++;
  697. printf("S[V]PPPtnextn");
  698. if(!iterator.next())
  699. return die_("iterator ended earlyn");
  700. our_current_position++;
  701. printf("SV[P]PPtdelete (middle block), replace with paddingn");
  702. if(!iterator.delete_block(true))
  703. return die_ss_("iterator.delete_block(true)", iterator);
  704. our_current_position--;
  705. printf("S[V]PPPtnextn");
  706. if(!iterator.next())
  707. return die_("iterator ended earlyn");
  708. our_current_position++;
  709. printf("SV[P]PPtdelete (middle block), don't replace with paddingn");
  710. if(!iterator.delete_block(false))
  711. return die_ss_("iterator.delete_block(false)", iterator);
  712. delete_from_our_metadata_(our_current_position--);
  713. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  714. return false;
  715. printf("S[V]PPtnextn");
  716. if(!iterator.next())
  717. return die_("iterator ended earlyn");
  718. our_current_position++;
  719. printf("SV[P]Ptnextn");
  720. if(!iterator.next())
  721. return die_("iterator ended earlyn");
  722. our_current_position++;
  723. printf("SVP[P]tdelete (last block), replace with paddingn");
  724. if(!iterator.delete_block(true))
  725. return die_ss_("iterator.delete_block(false)", iterator);
  726. our_current_position--;
  727. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  728. return false;
  729. printf("SV[P]Ptnextn");
  730. if(!iterator.next())
  731. return die_("iterator ended earlyn");
  732. our_current_position++;
  733. printf("SVP[P]tdelete (last block), don't replace with paddingn");
  734. if(!iterator.delete_block(false))
  735. return die_ss_("iterator.delete_block(false)", iterator);
  736. delete_from_our_metadata_(our_current_position--);
  737. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  738. return false;
  739. printf("SV[P]tprevn");
  740. if(!iterator.prev())
  741. return die_("iterator ended earlyn");
  742. our_current_position--;
  743. printf("S[V]Ptprevn");
  744. if(!iterator.prev())
  745. return die_("iterator ended earlyn");
  746. our_current_position--;
  747. printf("[S]VPtset STREAMINFO (change sample rate)n");
  748. FLAC__ASSERT(our_current_position == 0);
  749. block = iterator.get_block();
  750. streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
  751. FLAC__ASSERT(0 != streaminfo);
  752. streaminfo->set_sample_rate(32000);
  753. if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
  754. return die_("copying object");
  755. if(!iterator.set_block(block, false))
  756. return die_ss_("iterator.set_block(block, false)", iterator);
  757. delete block;
  758. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  759. return false;
  760. printf("[S]VPtnextn");
  761. if(!iterator.next())
  762. return die_("iterator ended earlyn");
  763. our_current_position++;
  764. printf("S[V]Ptinsert APPLICATION after, expand into padding of exceeding sizen");
  765. app->set_id((const unsigned char *)"euh"); /* twiddle the id so that our comparison doesn't miss transposition */
  766. if(!iterator.insert_block_after(app, true))
  767. return die_ss_("iterator.insert_block_after(app, true)", iterator);
  768. if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
  769. return false;
  770. add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
  771. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  772. return false;
  773. printf("SV[A]Ptnextn");
  774. if(!iterator.next())
  775. return die_("iterator ended earlyn");
  776. our_current_position++;
  777. printf("SVA[P]tset APPLICATION, expand into padding of exceeding sizen");
  778. app->set_id((const unsigned char *)"fuh"); /* twiddle the id */
  779. if(!iterator.set_block(app, true))
  780. return die_ss_("iterator.set_block(app, true)", iterator);
  781. if(!insert_to_our_metadata_(app, our_current_position, /*copy=*/true))
  782. return false;
  783. add_to_padding_length_(our_current_position+1, -((int)(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) + (int)app->get_length()));
  784. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  785. return false;
  786. printf("SVA[A]Ptset APPLICATION (grow), don't expand into paddingn");
  787. app->set_id((const unsigned char *)"guh"); /* twiddle the id */
  788. if(!app->set_data(data, sizeof(data), true))
  789. return die_("setting APPLICATION data");
  790. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  791. return die_("copying object");
  792. if(!iterator.set_block(app, false))
  793. return die_ss_("iterator.set_block(app, false)", iterator);
  794. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  795. return false;
  796. printf("SVA[A]Ptset APPLICATION (shrink), don't fill in with paddingn");
  797. app->set_id((const unsigned char *)"huh"); /* twiddle the id */
  798. if(!app->set_data(data, 12, true))
  799. return die_("setting APPLICATION data");
  800. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  801. return die_("copying object");
  802. if(!iterator.set_block(app, false))
  803. return die_ss_("iterator.set_block(app, false)", iterator);
  804. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  805. return false;
  806. printf("SVA[A]Ptset APPLICATION (grow), expand into padding of exceeding sizen");
  807. app->set_id((const unsigned char *)"iuh"); /* twiddle the id */
  808. if(!app->set_data(data, sizeof(data), true))
  809. return die_("setting APPLICATION data");
  810. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  811. return die_("copying object");
  812. add_to_padding_length_(our_current_position+1, -((int)sizeof(data) - 12));
  813. if(!iterator.set_block(app, true))
  814. return die_ss_("iterator.set_block(app, true)", iterator);
  815. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  816. return false;
  817. printf("SVA[A]Ptset APPLICATION (shrink), fill in with paddingn");
  818. app->set_id((const unsigned char *)"juh"); /* twiddle the id */
  819. if(!app->set_data(data, 23, true))
  820. return die_("setting APPLICATION data");
  821. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  822. return die_("copying object");
  823. if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/true))
  824. return die_("copying object");
  825. dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(sizeof(data) - 23 - FLAC__STREAM_METADATA_HEADER_LENGTH);
  826. if(!iterator.set_block(app, true))
  827. return die_ss_("iterator.set_block(app, true)", iterator);
  828. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  829. return false;
  830. printf("SVA[A]PPtnextn");
  831. if(!iterator.next())
  832. return die_("iterator ended earlyn");
  833. our_current_position++;
  834. printf("SVAA[P]Ptnextn");
  835. if(!iterator.next())
  836. return die_("iterator ended earlyn");
  837. our_current_position++;
  838. printf("SVAAP[P]tset PADDING (shrink), don't fill in with paddingn");
  839. padding->set_length(5);
  840. if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
  841. return die_("copying object");
  842. if(!iterator.set_block(padding, false))
  843. return die_ss_("iterator.set_block(padding, false)", iterator);
  844. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  845. return false;
  846. printf("SVAAP[P]tset APPLICATION (grow)n");
  847. app->set_id((const unsigned char *)"kuh"); /* twiddle the id */
  848. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  849. return die_("copying object");
  850. if(!iterator.set_block(app, false))
  851. return die_ss_("iterator.set_block(app, false)", iterator);
  852. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  853. return false;
  854. printf("SVAAP[A]tset PADDING (equal)n");
  855. padding->set_length(27);
  856. if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
  857. return die_("copying object");
  858. if(!iterator.set_block(padding, false))
  859. return die_ss_("iterator.set_block(padding, false)", iterator);
  860. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  861. return false;
  862. printf("SVAAP[P]tprevn");
  863. if(!iterator.prev())
  864. return die_("iterator ended earlyn");
  865. our_current_position--;
  866. printf("SVAA[P]Ptdelete (middle block), don't replace with paddingn");
  867. if(!iterator.delete_block(false))
  868. return die_ss_("iterator.delete_block(false)", iterator);
  869. delete_from_our_metadata_(our_current_position--);
  870. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  871. return false;
  872. printf("SVA[A]Ptdelete (middle block), don't replace with paddingn");
  873. if(!iterator.delete_block(false))
  874. return die_ss_("iterator.delete_block(false)", iterator);
  875. delete_from_our_metadata_(our_current_position--);
  876. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  877. return false;
  878. printf("SV[A]Ptnextn");
  879. if(!iterator.next())
  880. return die_("iterator ended earlyn");
  881. our_current_position++;
  882. printf("SVA[P]tinsert PADDING aftern");
  883. padding->set_length(5);
  884. if(!iterator.insert_block_after(padding, false))
  885. return die_ss_("iterator.insert_block_after(padding, false)", iterator);
  886. if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
  887. return false;
  888. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  889. return false;
  890. printf("SVAP[P]tprevn");
  891. if(!iterator.prev())
  892. return die_("iterator ended earlyn");
  893. our_current_position--;
  894. printf("SVA[P]Ptprevn");
  895. if(!iterator.prev())
  896. return die_("iterator ended earlyn");
  897. our_current_position--;
  898. printf("SV[A]PPtset APPLICATION (grow), try to expand into padding which is too smalln");
  899. if(!app->set_data(data, 32, true))
  900. return die_("setting APPLICATION data");
  901. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  902. return die_("copying object");
  903. if(!iterator.set_block(app, true))
  904. return die_ss_("iterator.set_block(app, true)", iterator);
  905. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  906. return false;
  907. printf("SV[A]PPtset APPLICATION (grow), try to expand into padding which is 'close' but still too smalln");
  908. if(!app->set_data(data, 60, true))
  909. return die_("setting APPLICATION data");
  910. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  911. return die_("copying object");
  912. if(!iterator.set_block(app, true))
  913. return die_ss_("iterator.set_block(app, true)", iterator);
  914. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  915. return false;
  916. printf("SV[A]PPtset APPLICATION (grow), expand into padding which will leave 0-length padn");
  917. if(!app->set_data(data, 87, true))
  918. return die_("setting APPLICATION data");
  919. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  920. return die_("copying object");
  921. dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
  922. if(!iterator.set_block(app, true))
  923. return die_ss_("iterator.set_block(app, true)", iterator);
  924. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  925. return false;
  926. printf("SV[A]PPtset APPLICATION (grow), expand into padding which is exactly consumedn");
  927. if(!app->set_data(data, 91, true))
  928. return die_("setting APPLICATION data");
  929. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  930. return die_("copying object");
  931. delete_from_our_metadata_(our_current_position+1);
  932. if(!iterator.set_block(app, true))
  933. return die_ss_("iterator.set_block(app, true)", iterator);
  934. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  935. return false;
  936. printf("SV[A]Ptset APPLICATION (grow), expand into padding which is exactly consumedn");
  937. if(!app->set_data(data, 100, true))
  938. return die_("setting APPLICATION data");
  939. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  940. return die_("copying object");
  941. delete_from_our_metadata_(our_current_position+1);
  942. our_metadata_.blocks[our_current_position]->set_is_last(true);
  943. if(!iterator.set_block(app, true))
  944. return die_ss_("iterator.set_block(app, true)", iterator);
  945. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  946. return false;
  947. printf("SV[A]tset PADDING (equal size)n");
  948. padding->set_length(app->get_length());
  949. if(!replace_in_our_metadata_(padding, our_current_position, /*copy=*/true))
  950. return die_("copying object");
  951. if(!iterator.set_block(padding, true))
  952. return die_ss_("iterator.set_block(padding, true)", iterator);
  953. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  954. return false;
  955. printf("SV[P]tinsert PADDING aftern");
  956. if(!iterator.insert_block_after(padding, false))
  957. return die_ss_("iterator.insert_block_after(padding, false)", iterator);
  958. if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
  959. return false;
  960. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  961. return false;
  962. printf("SVP[P]tinsert PADDING aftern");
  963. padding->set_length(5);
  964. if(!iterator.insert_block_after(padding, false))
  965. return die_ss_("iterator.insert_block_after(padding, false)", iterator);
  966. if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
  967. return false;
  968. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  969. return false;
  970. printf("SVPP[P]tprevn");
  971. if(!iterator.prev())
  972. return die_("iterator ended earlyn");
  973. our_current_position--;
  974. printf("SVP[P]Ptprevn");
  975. if(!iterator.prev())
  976. return die_("iterator ended earlyn");
  977. our_current_position--;
  978. printf("SV[P]PPtprevn");
  979. if(!iterator.prev())
  980. return die_("iterator ended earlyn");
  981. our_current_position--;
  982. printf("S[V]PPPtinsert APPLICATION after, try to expand into padding which is too smalln");
  983. if(!app->set_data(data, 101, true))
  984. return die_("setting APPLICATION data");
  985. if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
  986. return die_("copying object");
  987. if(!iterator.insert_block_after(app, true))
  988. return die_ss_("iterator.insert_block_after(app, true)", iterator);
  989. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  990. return false;
  991. printf("SV[A]PPPtdelete (middle block), don't replace with paddingn");
  992. if(!iterator.delete_block(false))
  993. return die_ss_("iterator.delete_block(false)", iterator);
  994. delete_from_our_metadata_(our_current_position--);
  995. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  996. return false;
  997. printf("S[V]PPPtinsert APPLICATION after, try to expand into padding which is 'close' but still too smalln");
  998. if(!app->set_data(data, 97, true))
  999. return die_("setting APPLICATION data");
  1000. if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
  1001. return die_("copying object");
  1002. if(!iterator.insert_block_after(app, true))
  1003. return die_ss_("iterator.insert_block_after(app, true)", iterator);
  1004. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1005. return false;
  1006. printf("SV[A]PPPtdelete (middle block), don't replace with paddingn");
  1007. if(!iterator.delete_block(false))
  1008. return die_ss_("iterator.delete_block(false)", iterator);
  1009. delete_from_our_metadata_(our_current_position--);
  1010. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1011. return false;
  1012. printf("S[V]PPPtinsert APPLICATION after, expand into padding which is exactly consumedn");
  1013. if(!app->set_data(data, 100, true))
  1014. return die_("setting APPLICATION data");
  1015. if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
  1016. return die_("copying object");
  1017. delete_from_our_metadata_(our_current_position+1);
  1018. if(!iterator.insert_block_after(app, true))
  1019. return die_ss_("iterator.insert_block_after(app, true)", iterator);
  1020. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1021. return false;
  1022. printf("SV[A]PPtdelete (middle block), don't replace with paddingn");
  1023. if(!iterator.delete_block(false))
  1024. return die_ss_("iterator.delete_block(false)", iterator);
  1025. delete_from_our_metadata_(our_current_position--);
  1026. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1027. return false;
  1028. printf("S[V]PPtinsert APPLICATION after, expand into padding which will leave 0-length padn");
  1029. if(!app->set_data(data, 96, true))
  1030. return die_("setting APPLICATION data");
  1031. if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
  1032. return die_("copying object");
  1033. dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(0);
  1034. if(!iterator.insert_block_after(app, true))
  1035. return die_ss_("iterator.insert_block_after(app, true)", iterator);
  1036. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1037. return false;
  1038. printf("SV[A]PPtdelete (middle block), don't replace with paddingn");
  1039. if(!iterator.delete_block(false))
  1040. return die_ss_("iterator.delete_block(false)", iterator);
  1041. delete_from_our_metadata_(our_current_position--);
  1042. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1043. return false;
  1044. printf("S[V]PPtnextn");
  1045. if(!iterator.next())
  1046. return die_("iterator ended earlyn");
  1047. our_current_position++;
  1048. printf("SV[P]Ptdelete (middle block), don't replace with paddingn");
  1049. if(!iterator.delete_block(false))
  1050. return die_ss_("iterator.delete_block(false)", iterator);
  1051. delete_from_our_metadata_(our_current_position--);
  1052. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1053. return false;
  1054. printf("S[V]Ptinsert APPLICATION after, expand into padding which is exactly consumedn");
  1055. if(!app->set_data(data, 1, true))
  1056. return die_("setting APPLICATION data");
  1057. if(!insert_to_our_metadata_(app, ++our_current_position, /*copy=*/true))
  1058. return die_("copying object");
  1059. delete_from_our_metadata_(our_current_position+1);
  1060. if(!iterator.insert_block_after(app, true))
  1061. return die_ss_("iterator.insert_block_after(app, true)", iterator);
  1062. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1063. return false;
  1064. }
  1065. delete app;
  1066. delete padding;
  1067. if(!remove_file_(flacfile_))
  1068. return false;
  1069. return true;
  1070. }
  1071. static bool test_level_2_(bool filename_based)
  1072. {
  1073. FLAC::Metadata::Prototype *block;
  1074. FLAC::Metadata::StreamInfo *streaminfo;
  1075. FLAC::Metadata::Application *app;
  1076. FLAC::Metadata::Padding *padding;
  1077. FLAC__byte data[2000];
  1078. unsigned our_current_position;
  1079. // initialize 'data' to avoid Valgrind errors
  1080. memset(data, 0, sizeof(data));
  1081. printf("nn++++++ testing level 2 interface (%s-based)n", filename_based? "filename":"callback");
  1082. printf("generate read-only filen");
  1083. if(!generate_file_())
  1084. return false;
  1085. if(!change_stats_(flacfile_, /*read_only=*/true))
  1086. return false;
  1087. printf("create chainn");
  1088. FLAC::Metadata::Chain chain;
  1089. if(!chain.is_valid())
  1090. return die_("allocating memory for chain");
  1091. printf("read chainn");
  1092. if(!read_chain_(chain, flacfile_, filename_based))
  1093. return die_c_("reading chain", chain.status());
  1094. printf("[S]VPttest initial metadatan");
  1095. if(!compare_chain_(chain, 0, 0))
  1096. return false;
  1097. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1098. return false;
  1099. printf("switch file to read-writen");
  1100. if(!change_stats_(flacfile_, /*read-only=*/false))
  1101. return false;
  1102. printf("create iteratorn");
  1103. {
  1104. FLAC::Metadata::Iterator iterator;
  1105. if(!iterator.is_valid())
  1106. return die_("allocating memory for iterator");
  1107. our_current_position = 0;
  1108. iterator.init(chain);
  1109. if(0 == (block = iterator.get_block()))
  1110. return die_("getting block from iterator");
  1111. FLAC__ASSERT(block->get_type() == FLAC__METADATA_TYPE_STREAMINFO);
  1112. printf("[S]VPtmodify STREAMINFO, writen");
  1113. streaminfo = dynamic_cast<FLAC::Metadata::StreamInfo *>(block);
  1114. FLAC__ASSERT(0 != streaminfo);
  1115. streaminfo->set_sample_rate(32000);
  1116. if(!replace_in_our_metadata_(block, our_current_position, /*copy=*/true))
  1117. return die_("copying object");
  1118. delete block;
  1119. if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/true, filename_based, flacfile_))
  1120. return die_c_("during chain.write(false, true)", chain.status());
  1121. block = iterator.get_block();
  1122. if(!compare_chain_(chain, our_current_position, block))
  1123. return false;
  1124. delete block;
  1125. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1126. return false;
  1127. printf("[S]VPtnextn");
  1128. if(!iterator.next())
  1129. return die_("iterator ended earlyn");
  1130. our_current_position++;
  1131. printf("S[V]Ptnextn");
  1132. if(!iterator.next())
  1133. return die_("iterator ended earlyn");
  1134. our_current_position++;
  1135. printf("SV[P]treplace PADDING with identical-size APPLICATIONn");
  1136. if(0 == (block = iterator.get_block()))
  1137. return die_("getting block from iterator");
  1138. if(0 == (app = new FLAC::Metadata::Application()))
  1139. return die_("new FLAC::Metadata::Application()");
  1140. app->set_id((const unsigned char *)"duh");
  1141. if(!app->set_data(data, block->get_length()-(FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), true))
  1142. return die_("setting APPLICATION data");
  1143. delete block;
  1144. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1145. return die_("copying object");
  1146. if(!iterator.set_block(app))
  1147. return die_c_("iterator.set_block(app)", chain.status());
  1148. if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1149. return die_c_("during chain.write(false, false)", chain.status());
  1150. block = iterator.get_block();
  1151. if(!compare_chain_(chain, our_current_position, block))
  1152. return false;
  1153. delete block;
  1154. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1155. return false;
  1156. printf("SV[A]tshrink APPLICATION, don't use paddingn");
  1157. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1158. return die_("copying object");
  1159. if(!app->set_data(data, 26, true))
  1160. return die_("setting APPLICATION data");
  1161. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1162. return die_("copying object");
  1163. if(!iterator.set_block(app))
  1164. return die_c_("iterator.set_block(app)", chain.status());
  1165. if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1166. return die_c_("during chain.write(false, false)", chain.status());
  1167. block = iterator.get_block();
  1168. if(!compare_chain_(chain, our_current_position, block))
  1169. return false;
  1170. delete block;
  1171. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1172. return false;
  1173. printf("SV[A]tgrow APPLICATION, don't use paddingn");
  1174. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1175. return die_("copying object");
  1176. if(!app->set_data(data, 28, true))
  1177. return die_("setting APPLICATION data");
  1178. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1179. return die_("copying object");
  1180. if(!iterator.set_block(app))
  1181. return die_c_("iterator.set_block(app)", chain.status());
  1182. if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1183. return die_c_("during chain.write(false, false)", chain.status());
  1184. block = iterator.get_block();
  1185. if(!compare_chain_(chain, our_current_position, block))
  1186. return false;
  1187. delete block;
  1188. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1189. return false;
  1190. printf("SV[A]tgrow APPLICATION, use padding, but last block is not paddingn");
  1191. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1192. return die_("copying object");
  1193. if(!app->set_data(data, 36, true))
  1194. return die_("setting APPLICATION data");
  1195. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1196. return die_("copying object");
  1197. if(!iterator.set_block(app))
  1198. return die_c_("iterator.set_block(app)", chain.status());
  1199. if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1200. return die_c_("during chain.write(false, false)", chain.status());
  1201. block = iterator.get_block();
  1202. if(!compare_chain_(chain, our_current_position, block))
  1203. return false;
  1204. delete block;
  1205. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1206. return false;
  1207. printf("SV[A]tshrink APPLICATION, use padding, last block is not padding, but delta is too small for new PADDING blockn");
  1208. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1209. return die_("copying object");
  1210. if(!app->set_data(data, 33, true))
  1211. return die_("setting APPLICATION data");
  1212. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1213. return die_("copying object");
  1214. if(!iterator.set_block(app))
  1215. return die_c_("iterator.set_block(app)", chain.status());
  1216. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1217. return die_c_("during chain.write(true, false)", chain.status());
  1218. block = iterator.get_block();
  1219. if(!compare_chain_(chain, our_current_position, block))
  1220. return false;
  1221. delete block;
  1222. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1223. return false;
  1224. printf("SV[A]tshrink APPLICATION, use padding, last block is not padding, delta is enough for new PADDING blockn");
  1225. if(0 == (padding = new FLAC::Metadata::Padding()))
  1226. return die_("creating PADDING block");
  1227. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1228. return die_("copying object");
  1229. if(!app->set_data(data, 29, true))
  1230. return die_("setting APPLICATION data");
  1231. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1232. return die_("copying object");
  1233. padding->set_length(0);
  1234. if(!insert_to_our_metadata_(padding, our_current_position+1, /*copy=*/false))
  1235. return die_("internal error");
  1236. if(!iterator.set_block(app))
  1237. return die_c_("iterator.set_block(app)", chain.status());
  1238. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1239. return die_c_("during chain.write(true, false)", chain.status());
  1240. block = iterator.get_block();
  1241. if(!compare_chain_(chain, our_current_position, block))
  1242. return false;
  1243. delete block;
  1244. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1245. return false;
  1246. printf("SV[A]Ptshrink APPLICATION, use padding, last block is paddingn");
  1247. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1248. return die_("copying object");
  1249. if(!app->set_data(data, 16, true))
  1250. return die_("setting APPLICATION data");
  1251. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1252. return die_("copying object");
  1253. dynamic_cast<FLAC::Metadata::Padding *>(our_metadata_.blocks[our_current_position+1])->set_length(13);
  1254. if(!iterator.set_block(app))
  1255. return die_c_("iterator.set_block(app)", chain.status());
  1256. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1257. return die_c_("during chain.write(true, false)", chain.status());
  1258. block = iterator.get_block();
  1259. if(!compare_chain_(chain, our_current_position, block))
  1260. return false;
  1261. delete block;
  1262. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1263. return false;
  1264. printf("SV[A]Ptgrow APPLICATION, use padding, last block is padding, but delta is too smalln");
  1265. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1266. return die_("copying object");
  1267. if(!app->set_data(data, 50, true))
  1268. return die_("setting APPLICATION data");
  1269. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1270. return die_("copying object");
  1271. if(!iterator.set_block(app))
  1272. return die_c_("iterator.set_block(app)", chain.status());
  1273. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1274. return die_c_("during chain.write(true, false)", chain.status());
  1275. block = iterator.get_block();
  1276. if(!compare_chain_(chain, our_current_position, block))
  1277. return false;
  1278. delete block;
  1279. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1280. return false;
  1281. printf("SV[A]Ptgrow APPLICATION, use padding, last block is padding of exceeding sizen");
  1282. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1283. return die_("copying object");
  1284. if(!app->set_data(data, 56, true))
  1285. return die_("setting APPLICATION data");
  1286. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1287. return die_("copying object");
  1288. add_to_padding_length_(our_current_position+1, -(56 - 50));
  1289. if(!iterator.set_block(app))
  1290. return die_c_("iterator.set_block(app)", chain.status());
  1291. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1292. return die_c_("during chain.write(true, false)", chain.status());
  1293. block = iterator.get_block();
  1294. if(!compare_chain_(chain, our_current_position, block))
  1295. return false;
  1296. delete block;
  1297. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1298. return false;
  1299. printf("SV[A]Ptgrow APPLICATION, use padding, last block is padding of exact sizen");
  1300. if(0 == (app = dynamic_cast<FLAC::Metadata::Application *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1301. return die_("copying object");
  1302. if(!app->set_data(data, 67, true))
  1303. return die_("setting APPLICATION data");
  1304. if(!replace_in_our_metadata_(app, our_current_position, /*copy=*/true))
  1305. return die_("copying object");
  1306. delete_from_our_metadata_(our_current_position+1);
  1307. if(!iterator.set_block(app))
  1308. return die_c_("iterator.set_block(app)", chain.status());
  1309. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1310. return die_c_("during chain.write(true, false)", chain.status());
  1311. block = iterator.get_block();
  1312. if(!compare_chain_(chain, our_current_position, block))
  1313. return false;
  1314. delete block;
  1315. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1316. return false;
  1317. printf("SV[A]tprevn");
  1318. if(!iterator.prev())
  1319. return die_("iterator ended earlyn");
  1320. our_current_position--;
  1321. printf("S[V]Atprevn");
  1322. if(!iterator.prev())
  1323. return die_("iterator ended earlyn");
  1324. our_current_position--;
  1325. printf("[S]VAtinsert PADDING before STREAMINFO (should fail)n");
  1326. if(0 == (padding = new FLAC::Metadata::Padding()))
  1327. return die_("creating PADDING block");
  1328. padding->set_length(30);
  1329. if(!iterator.insert_block_before(padding))
  1330. printf("titerator.insert_block_before() returned false like it shouldn");
  1331. else
  1332. return die_("iterator.insert_block_before() should have returned false");
  1333. printf("[S]VAtnextn");
  1334. if(!iterator.next())
  1335. return die_("iterator ended earlyn");
  1336. our_current_position++;
  1337. printf("S[V]Atinsert PADDING aftern");
  1338. if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
  1339. return die_("copying metadata");
  1340. if(!iterator.insert_block_after(padding))
  1341. return die_("iterator.insert_block_after(padding)");
  1342. block = iterator.get_block();
  1343. if(!compare_chain_(chain, our_current_position, block))
  1344. return false;
  1345. delete block;
  1346. printf("SV[P]Atinsert PADDING beforen");
  1347. if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1348. return die_("creating PADDING block");
  1349. padding->set_length(17);
  1350. if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
  1351. return die_("copying metadata");
  1352. if(!iterator.insert_block_before(padding))
  1353. return die_("iterator.insert_block_before(padding)");
  1354. block = iterator.get_block();
  1355. if(!compare_chain_(chain, our_current_position, block))
  1356. return false;
  1357. delete block;
  1358. printf("SV[P]PAtinsert PADDING beforen");
  1359. if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[our_current_position]))))
  1360. return die_("creating PADDING block");
  1361. padding->set_length(0);
  1362. if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
  1363. return die_("copying metadata");
  1364. if(!iterator.insert_block_before(padding))
  1365. return die_("iterator.insert_block_before(padding)");
  1366. block = iterator.get_block();
  1367. if(!compare_chain_(chain, our_current_position, block))
  1368. return false;
  1369. delete block;
  1370. printf("SV[P]PPAtnextn");
  1371. if(!iterator.next())
  1372. return die_("iterator ended earlyn");
  1373. our_current_position++;
  1374. printf("SVP[P]PAtnextn");
  1375. if(!iterator.next())
  1376. return die_("iterator ended earlyn");
  1377. our_current_position++;
  1378. printf("SVPP[P]Atnextn");
  1379. if(!iterator.next())
  1380. return die_("iterator ended earlyn");
  1381. our_current_position++;
  1382. printf("SVPPP[A]tinsert PADDING aftern");
  1383. if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
  1384. return die_("creating PADDING block");
  1385. padding->set_length(57);
  1386. if(!insert_to_our_metadata_(padding, ++our_current_position, /*copy=*/true))
  1387. return die_("copying metadata");
  1388. if(!iterator.insert_block_after(padding))
  1389. return die_("iterator.insert_block_after(padding)");
  1390. block = iterator.get_block();
  1391. if(!compare_chain_(chain, our_current_position, block))
  1392. return false;
  1393. delete block;
  1394. printf("SVPPPA[P]tinsert PADDING beforen");
  1395. if(0 == (padding = dynamic_cast<FLAC::Metadata::Padding *>(FLAC::Metadata::clone(our_metadata_.blocks[2]))))
  1396. return die_("creating PADDING block");
  1397. padding->set_length(99);
  1398. if(!insert_to_our_metadata_(padding, our_current_position, /*copy=*/true))
  1399. return die_("copying metadata");
  1400. if(!iterator.insert_block_before(padding))
  1401. return die_("iterator.insert_block_before(padding)");
  1402. block = iterator.get_block();
  1403. if(!compare_chain_(chain, our_current_position, block))
  1404. return false;
  1405. delete block;
  1406. }
  1407. our_current_position = 0;
  1408. printf("SVPPPAPPtmerge paddingn");
  1409. chain.merge_padding();
  1410. add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[3]->get_length());
  1411. add_to_padding_length_(2, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[4]->get_length());
  1412. add_to_padding_length_(6, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[7]->get_length());
  1413. delete_from_our_metadata_(7);
  1414. delete_from_our_metadata_(4);
  1415. delete_from_our_metadata_(3);
  1416. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1417. return die_c_("during chain.write(true, false)", chain.status());
  1418. if(!compare_chain_(chain, 0, 0))
  1419. return false;
  1420. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1421. return false;
  1422. printf("SVPAPtsort paddingn");
  1423. chain.sort_padding();
  1424. add_to_padding_length_(4, FLAC__STREAM_METADATA_HEADER_LENGTH + our_metadata_.blocks[2]->get_length());
  1425. delete_from_our_metadata_(2);
  1426. if(!write_chain_(chain, /*use_padding=*/true, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1427. return die_c_("during chain.write(true, false)", chain.status());
  1428. if(!compare_chain_(chain, 0, 0))
  1429. return false;
  1430. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1431. return false;
  1432. printf("create iteratorn");
  1433. {
  1434. FLAC::Metadata::Iterator iterator;
  1435. if(!iterator.is_valid())
  1436. return die_("allocating memory for iterator");
  1437. our_current_position = 0;
  1438. iterator.init(chain);
  1439. printf("[S]VAPtnextn");
  1440. if(!iterator.next())
  1441. return die_("iterator ended earlyn");
  1442. our_current_position++;
  1443. printf("S[V]APtnextn");
  1444. if(!iterator.next())
  1445. return die_("iterator ended earlyn");
  1446. our_current_position++;
  1447. printf("SV[A]Ptdelete middle block, replace with paddingn");
  1448. if(0 == (padding = new FLAC::Metadata::Padding()))
  1449. return die_("creating PADDING block");
  1450. padding->set_length(71);
  1451. if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
  1452. return die_("copying object");
  1453. if(!iterator.delete_block(/*replace_with_padding=*/true))
  1454. return die_c_("iterator.delete_block(true)", chain.status());
  1455. block = iterator.get_block();
  1456. if(!compare_chain_(chain, our_current_position, block))
  1457. return false;
  1458. delete block;
  1459. printf("S[V]PPtnextn");
  1460. if(!iterator.next())
  1461. return die_("iterator ended earlyn");
  1462. our_current_position++;
  1463. printf("SV[P]Ptdelete middle block, don't replace with paddingn");
  1464. delete_from_our_metadata_(our_current_position--);
  1465. if(!iterator.delete_block(/*replace_with_padding=*/false))
  1466. return die_c_("iterator.delete_block(false)", chain.status());
  1467. block = iterator.get_block();
  1468. if(!compare_chain_(chain, our_current_position, block))
  1469. return false;
  1470. delete block;
  1471. printf("S[V]Ptnextn");
  1472. if(!iterator.next())
  1473. return die_("iterator ended earlyn");
  1474. our_current_position++;
  1475. printf("SV[P]tdelete last block, replace with paddingn");
  1476. if(0 == (padding = new FLAC::Metadata::Padding()))
  1477. return die_("creating PADDING block");
  1478. padding->set_length(219);
  1479. if(!replace_in_our_metadata_(padding, our_current_position--, /*copy=*/false))
  1480. return die_("copying object");
  1481. if(!iterator.delete_block(/*replace_with_padding=*/true))
  1482. return die_c_("iterator.delete_block(true)", chain.status());
  1483. block = iterator.get_block();
  1484. if(!compare_chain_(chain, our_current_position, block))
  1485. return false;
  1486. delete block;
  1487. printf("S[V]Ptnextn");
  1488. if(!iterator.next())
  1489. return die_("iterator ended earlyn");
  1490. our_current_position++;
  1491. printf("SV[P]tdelete last block, don't replace with paddingn");
  1492. delete_from_our_metadata_(our_current_position--);
  1493. if(!iterator.delete_block(/*replace_with_padding=*/false))
  1494. return die_c_("iterator.delete_block(false)", chain.status());
  1495. block = iterator.get_block();
  1496. if(!compare_chain_(chain, our_current_position, block))
  1497. return false;
  1498. delete block;
  1499. printf("S[V]tprevn");
  1500. if(!iterator.prev())
  1501. return die_("iterator ended earlyn");
  1502. our_current_position--;
  1503. printf("[S]Vtdelete STREAMINFO block, should failn");
  1504. if(iterator.delete_block(/*replace_with_padding=*/false))
  1505. return die_("iterator.delete_block() on STREAMINFO should have failed but didn't");
  1506. block = iterator.get_block();
  1507. if(!compare_chain_(chain, our_current_position, block))
  1508. return false;
  1509. delete block;
  1510. } // delete iterator
  1511. our_current_position = 0;
  1512. printf("SVtmerge paddingn");
  1513. chain.merge_padding();
  1514. if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1515. return die_c_("during chain.write(false, false)", chain.status());
  1516. if(!compare_chain_(chain, 0, 0))
  1517. return false;
  1518. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1519. return false;
  1520. printf("SVtsort paddingn");
  1521. chain.sort_padding();
  1522. if(!write_chain_(chain, /*use_padding=*/false, /*preserve_file_stats=*/false, filename_based, flacfile_))
  1523. return die_c_("during chain.write(false, false)", chain.status());
  1524. if(!compare_chain_(chain, 0, 0))
  1525. return false;
  1526. if(!test_file_(flacfile_, /*ignore_metadata=*/false))
  1527. return false;
  1528. if(!remove_file_(flacfile_))
  1529. return false;
  1530. return true;
  1531. }
  1532. static bool test_level_2_misc_()
  1533. {
  1534. ::FLAC__IOCallbacks callbacks;
  1535. memset(&callbacks, 0, sizeof(callbacks));
  1536. callbacks.read = (::FLAC__IOCallback_Read)fread;
  1537. #ifdef FLAC__VALGRIND_TESTING
  1538. callbacks.write = chain_write_cb_;
  1539. #else
  1540. callbacks.write = (::FLAC__IOCallback_Write)fwrite;
  1541. #endif
  1542. callbacks.seek = chain_seek_cb_;
  1543. callbacks.tell = chain_tell_cb_;
  1544. callbacks.eof = chain_eof_cb_;
  1545. printf("nn++++++ testing level 2 interface (mismatched read/write protections)n");
  1546. printf("generate filen");
  1547. if(!generate_file_())
  1548. return false;
  1549. printf("create chainn");
  1550. FLAC::Metadata::Chain chain;
  1551. if(!chain.is_valid())
  1552. return die_("allocating chain");
  1553. printf("read chain (filename-based)n");
  1554. if(!chain.read(flacfile_))
  1555. return die_c_("reading chain", chain.status());
  1556. printf("write chain with wrong method Chain::write(with callbacks)n");
  1557. {
  1558. if(chain.write(/*use_padding=*/false, 0, callbacks))
  1559. return die_c_("mismatched write should have failed", chain.status());
  1560. if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
  1561. return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
  1562. printf("  OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it shouldn");
  1563. }
  1564. printf("read chain (filename-based)n");
  1565. if(!chain.read(flacfile_))
  1566. return die_c_("reading chain", chain.status());
  1567. printf("write chain with wrong method Chain::write(with callbacks and tempfile)n");
  1568. {
  1569. if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
  1570. return die_c_("mismatched write should have failed", chain.status());
  1571. if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
  1572. return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
  1573. printf("  OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it shouldn");
  1574. }
  1575. printf("read chain (callback-based)n");
  1576. {
  1577. FILE *file = fopen(flacfile_, "rb");
  1578. if(0 == file)
  1579. return die_("opening file");
  1580. if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
  1581. fclose(file);
  1582. return die_c_("reading chain", chain.status());
  1583. }
  1584. fclose(file);
  1585. }
  1586. printf("write chain with wrong method write()n");
  1587. {
  1588. if(chain.write(/*use_padding=*/false, /*preserve_file_stats=*/false))
  1589. return die_c_("mismatched write should have failed", chain.status());
  1590. if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH)
  1591. return die_c_("expected FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", chain.status());
  1592. printf("  OK: write() returned false,FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH like it shouldn");
  1593. }
  1594. printf("read chain (callback-based)n");
  1595. {
  1596. FILE *file = fopen(flacfile_, "rb");
  1597. if(0 == file)
  1598. return die_("opening file");
  1599. if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
  1600. fclose(file);
  1601. return die_c_("reading chain", chain.status());
  1602. }
  1603. fclose(file);
  1604. }
  1605. printf("testing Chain::check_if_tempfile_needed()... ");
  1606. if(!chain.check_if_tempfile_needed(/*use_padding=*/false))
  1607. printf("OK: Chain::check_if_tempfile_needed() returned false like it shouldn");
  1608. else
  1609. return die_("Chain::check_if_tempfile_needed() returned true but shouldn't have");
  1610. printf("write chain with wrong method Chain::write(with callbacks and tempfile)n");
  1611. {
  1612. if(chain.write(/*use_padding=*/false, 0, callbacks, 0, callbacks))
  1613. return die_c_("mismatched write should have failed", chain.status());
  1614. if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
  1615. return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
  1616. printf("  OK: Chain::write(with callbacks and tempfile) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it shouldn");
  1617. }
  1618. printf("read chain (callback-based)n");
  1619. {
  1620. FILE *file = fopen(flacfile_, "rb");
  1621. if(0 == file)
  1622. return die_("opening file");
  1623. if(!chain.read((::FLAC__IOHandle)file, callbacks)) {
  1624. fclose(file);
  1625. return die_c_("reading chain", chain.status());
  1626. }
  1627. fclose(file);
  1628. }
  1629. printf("create iteratorn");
  1630. {
  1631. FLAC::Metadata::Iterator iterator;
  1632. if(!iterator.is_valid())
  1633. return die_("allocating memory for iterator");
  1634. iterator.init(chain);
  1635. printf("[S]VPtnextn");
  1636. if(!iterator.next())
  1637. return die_("iterator ended earlyn");
  1638. printf("S[V]Ptdelete VORBIS_COMMENT, writen");
  1639. if(!iterator.delete_block(/*replace_with_padding=*/false))
  1640. return die_c_("block delete failedn", chain.status());
  1641. printf("testing Chain::check_if_tempfile_needed()... ");
  1642. if(chain.check_if_tempfile_needed(/*use_padding=*/false))
  1643. printf("OK: Chain::check_if_tempfile_needed() returned true like it shouldn");
  1644. else
  1645. return die_("Chain::check_if_tempfile_needed() returned false but shouldn't have");
  1646. printf("write chain with wrong method Chain::write(with callbacks)n");
  1647. {
  1648. if(chain.write(/*use_padding=*/false, 0, callbacks))
  1649. return die_c_("mismatched write should have failed", chain.status());
  1650. if(chain.status() != ::FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL)
  1651. return die_c_("expected FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL", chain.status());
  1652. printf("  OK: Chain::write(with callbacks) returned false,FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL like it shouldn");
  1653. }
  1654. } // delete iterator
  1655. if(!remove_file_(flacfile_))
  1656. return false;
  1657. return true;
  1658. }
  1659. bool test_metadata_file_manipulation()
  1660. {
  1661. printf("n+++ libFLAC++ unit test: metadata manipulationnn");
  1662. our_metadata_.num_blocks = 0;
  1663. if(!test_level_0_())
  1664. return false;
  1665. if(!test_level_1_())
  1666. return false;
  1667. if(!test_level_2_(/*filename_based=*/true)) /* filename-based */
  1668. return false;
  1669. if(!test_level_2_(/*filename_based=*/false)) /* callback-based */
  1670. return false;
  1671. if(!test_level_2_misc_())
  1672. return false;
  1673. return true;
  1674. }