test_file_io.c
上传用户:shw771010
上传日期:2022-01-05
资源大小:991k
文件大小:14k
源码类别:

Audio

开发平台:

Unix_Linux

  1. /*
  2. ** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU Lesser General Public License as published by
  6. ** the Free Software Foundation; either version 2.1 of the License, or
  7. ** (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 Lesser General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU Lesser 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. #include "sfconfig.h"
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #if HAVE_UNISTD_H
  22. #include <unistd.h>
  23. #endif
  24. #include <string.h>
  25. #include <errno.h>
  26. #include <inttypes.h>
  27. #include "common.h"
  28. #include "test_main.h"
  29. static void make_data (int *data, int len, int seed) ;
  30. static void file_open_test (const char *filename) ;
  31. static void file_read_write_test (const char *filename) ;
  32. static void file_truncate_test (const char *filename) ;
  33. static void test_open_or_die (SF_PRIVATE *psf, int linenum) ;
  34. static void test_close_or_die (SF_PRIVATE *psf, int linenum) ;
  35. static void test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
  36. static void test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
  37. static void test_equal_or_die (int *array1, int *array2, int len, int linenum) ;
  38. static void test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum) ;
  39. /*==============================================================================
  40. ** Actual test functions.
  41. */
  42. static void
  43. file_open_test (const char *filename)
  44. { SF_PRIVATE sf_data, *psf ;
  45. int error ;
  46. print_test_name ("Testing file open") ;
  47. memset (&sf_data, 0, sizeof (sf_data)) ;
  48. psf = &sf_data ;
  49. /* Ensure that the file doesn't already exist. */
  50. if (unlink (filename) != 0 && errno != ENOENT)
  51. { printf ("nnLine %d: unlink failed (%d) : %snn", __LINE__, errno, strerror (errno)) ;
  52. exit (1) ;
  53. } ;
  54. psf->file.mode = SFM_READ ;
  55. snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
  56. /* Test that open for read fails if the file doesn't exist. */
  57. error = psf_fopen (psf) ;
  58. if (error == 0)
  59. { printf ("nnLine %d: psf_fopen() should have failed.nn", __LINE__) ;
  60. exit (1) ;
  61. } ;
  62. /* Reset error to zero. */
  63. psf->error = SFE_NO_ERROR ;
  64. /* Test file open in write mode. */
  65. psf->file.mode = SFM_WRITE ;
  66. test_open_or_die (psf, __LINE__) ;
  67. test_close_or_die (psf, __LINE__) ;
  68. unlink (psf->file.path.c) ;
  69. /* Test file open in read/write mode for a non-existant file. */
  70. psf->file.mode = SFM_RDWR ;
  71. test_open_or_die (psf, __LINE__) ;
  72. test_close_or_die (psf, __LINE__) ;
  73. /* Test file open in read/write mode for an existing file. */
  74. psf->file.mode = SFM_RDWR ;
  75. test_open_or_die (psf, __LINE__) ;
  76. test_close_or_die (psf, __LINE__) ;
  77. unlink (psf->file.path.c) ;
  78. puts ("ok") ;
  79. } /* file_open_test */
  80. static void
  81. file_read_write_test (const char *filename)
  82. { static int data_out [512] ;
  83. static int data_in [512] ;
  84. SF_PRIVATE sf_data, *psf ;
  85. sf_count_t retval ;
  86. /*
  87. ** Open a new file and write two blocks of data to the file. After each
  88. ** write, test that psf_get_filelen() returns the new length.
  89. */
  90. print_test_name ("Testing file write") ;
  91. memset (&sf_data, 0, sizeof (sf_data)) ;
  92. psf = &sf_data ;
  93. snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
  94. /* Test file open in write mode. */
  95. psf->file.mode = SFM_WRITE ;
  96. test_open_or_die (psf, __LINE__) ;
  97. make_data (data_out, ARRAY_LEN (data_out), 1) ;
  98. test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), sizeof (data_out), __LINE__) ;
  99. if ((retval = psf_get_filelen (psf)) != sizeof (data_out))
  100. { printf ("nnLine %d: file length after write is not correct (%" PRId64 " should be %zd).nn", __LINE__, retval, sizeof (data_out)) ;
  101. if (retval == 0)
  102. printf ("An fsync() may be necessary before fstat() in psf_get_filelen().nn") ;
  103. exit (1) ;
  104. } ;
  105. make_data (data_out, ARRAY_LEN (data_out), 2) ;
  106. test_write_or_die (psf, data_out, ARRAY_LEN (data_out), sizeof (data_out [0]), 2 * sizeof (data_out), __LINE__) ;
  107. if ((retval = psf_get_filelen (psf)) != 2 * sizeof (data_out))
  108. { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %zd)nn", __LINE__, retval, 2 * sizeof (data_out)) ;
  109. exit (1) ;
  110. } ;
  111. test_close_or_die (psf, __LINE__) ;
  112. puts ("ok") ;
  113. /*
  114. ** Now open the file in read mode, check the file length and check
  115. ** that the data is correct.
  116. */
  117. print_test_name ("Testing file read") ;
  118. /* Test file open in write mode. */
  119. psf->file.mode = SFM_READ ;
  120. test_open_or_die (psf, __LINE__) ;
  121. make_data (data_out, ARRAY_LEN (data_out), 1) ;
  122. test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
  123. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  124. make_data (data_out, ARRAY_LEN (data_out), 2) ;
  125. test_read_or_die (psf, data_in, sizeof (data_in [0]), ARRAY_LEN (data_in), 2 * sizeof (data_in), __LINE__) ;
  126. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  127. test_close_or_die (psf, __LINE__) ;
  128. puts ("ok") ;
  129. /*
  130. ** Open the file in read/write mode, seek around a bit and then seek to
  131. ** the end of the file and write another block of data (3rd block). Then
  132. ** go back and check that all three blocks are correct.
  133. */
  134. print_test_name ("Testing file seek") ;
  135. /* Test file open in read/write mode. */
  136. psf->file.mode = SFM_RDWR ;
  137. test_open_or_die (psf, __LINE__) ;
  138. test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
  139. test_seek_or_die (psf, 0, SEEK_END, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
  140. test_seek_or_die (psf, -1 * SIGNED_SIZEOF (data_out), SEEK_CUR, (sf_count_t) sizeof (data_out), __LINE__) ;
  141. test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_CUR, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
  142. make_data (data_out, ARRAY_LEN (data_out), 3) ;
  143. test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 3 * sizeof (data_out), __LINE__) ;
  144. test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
  145. make_data (data_out, ARRAY_LEN (data_out), 1) ;
  146. test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
  147. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  148. test_seek_or_die (psf, 2 * SIGNED_SIZEOF (data_out), SEEK_SET, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
  149. make_data (data_out, ARRAY_LEN (data_out), 3) ;
  150. test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
  151. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  152. test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
  153. make_data (data_out, ARRAY_LEN (data_out), 2) ;
  154. test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
  155. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  156. test_close_or_die (psf, __LINE__) ;
  157. puts ("ok") ;
  158. /*
  159. ** Now test operations with a non-zero psf->fileoffset field. This field
  160. ** sets an artificial file start positions so that a seek to the start of
  161. ** the file will actually be a seek to the value given by psf->fileoffset.
  162. */
  163. print_test_name ("Testing file offset") ;
  164. /* Test file open in read/write mode. */
  165. psf->file.mode = SFM_RDWR ;
  166. psf->fileoffset = sizeof (data_out [0]) * ARRAY_LEN (data_out) ;
  167. test_open_or_die (psf, __LINE__) ;
  168. if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
  169. { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %zd)nn", __LINE__, retval, 3 * sizeof (data_out)) ;
  170. exit (1) ;
  171. } ;
  172. test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
  173. make_data (data_out, ARRAY_LEN (data_out), 5) ;
  174. test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 2 * sizeof (data_out), __LINE__) ;
  175. test_close_or_die (psf, __LINE__) ;
  176. /* final test with psf->fileoffset == 0. */
  177. psf->file.mode = SFM_RDWR ;
  178. psf->fileoffset = 0 ;
  179. test_open_or_die (psf, __LINE__) ;
  180. if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
  181. { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %zd)nn", __LINE__, retval, 3 * sizeof (data_out)) ;
  182. exit (1) ;
  183. } ;
  184. make_data (data_out, ARRAY_LEN (data_out), 1) ;
  185. test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
  186. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  187. make_data (data_out, ARRAY_LEN (data_out), 2) ;
  188. test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
  189. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  190. make_data (data_out, ARRAY_LEN (data_out), 5) ;
  191. test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
  192. test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
  193. test_close_or_die (psf, __LINE__) ;
  194. puts ("ok") ;
  195. } /* file_read_write_test */
  196. static void
  197. file_truncate_test (const char *filename)
  198. { SF_PRIVATE sf_data, *psf ;
  199. unsigned char buffer [256] ;
  200. int k ;
  201. /*
  202. ** Open a new file and write two blocks of data to the file. After each
  203. ** write, test that psf_get_filelen() returns the new length.
  204. */
  205. print_test_name ("Testing file truncate") ;
  206. memset (&sf_data, 0, sizeof (sf_data)) ;
  207. memset (buffer, 0xEE, sizeof (buffer)) ;
  208. psf = &sf_data ;
  209. snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
  210. /*
  211. ** Open the file write mode, write 0xEE data and then extend the file
  212. ** using truncate (the extended data should be 0x00).
  213. */
  214. psf->file.mode = SFM_WRITE ;
  215. test_open_or_die (psf, __LINE__) ;
  216. test_write_or_die (psf, buffer, sizeof (buffer) / 2, 1, sizeof (buffer) / 2, __LINE__) ;
  217. psf_ftruncate (psf, sizeof (buffer)) ;
  218. test_close_or_die (psf, __LINE__) ;
  219. /* Open the file in read mode and check the data. */
  220. psf->file.mode = SFM_READ ;
  221. test_open_or_die (psf, __LINE__) ;
  222. test_read_or_die (psf, buffer, sizeof (buffer), 1, sizeof (buffer), __LINE__) ;
  223. test_close_or_die (psf, __LINE__) ;
  224. for (k = 0 ; k < SIGNED_SIZEOF (buffer) / 2 ; k++)
  225. if (buffer [k] != 0xEE)
  226. { printf ("nnLine %d : buffer [%d] = %d (should be 0xEE)nn", __LINE__, k, buffer [k]) ;
  227. exit (1) ;
  228. } ;
  229. for (k = SIGNED_SIZEOF (buffer) / 2 ; k < SIGNED_SIZEOF (buffer) ; k++)
  230. if (buffer [k] != 0)
  231. { printf ("nnLine %d : buffer [%d] = %d (should be 0)nn", __LINE__, k, buffer [k]) ;
  232. exit (1) ;
  233. } ;
  234. /* Open the file in read/write and shorten the file using truncate. */
  235. psf->file.mode = SFM_RDWR ;
  236. test_open_or_die (psf, __LINE__) ;
  237. psf_ftruncate (psf, sizeof (buffer) / 4) ;
  238. test_close_or_die (psf, __LINE__) ;
  239. /* Check the file length. */
  240. psf->file.mode = SFM_READ ;
  241. test_open_or_die (psf, __LINE__) ;
  242. test_seek_or_die (psf, 0, SEEK_END, SIGNED_SIZEOF (buffer) / 4, __LINE__) ;
  243. test_close_or_die (psf, __LINE__) ;
  244. puts ("ok") ;
  245. } /* file_truncate_test */
  246. /*==============================================================================
  247. ** Testing helper functions.
  248. */
  249. static void
  250. test_open_or_die (SF_PRIVATE *psf, int linenum)
  251. { int error ;
  252. /* Test that open for read fails if the file doesn't exist. */
  253. error = psf_fopen (psf) ;
  254. if (error)
  255. { printf ("nnLine %d: psf_fopen() failed : %snn", linenum, strerror (errno)) ;
  256. exit (1) ;
  257. } ;
  258. } /* test_open_or_die */
  259. static void
  260. test_close_or_die (SF_PRIVATE *psf, int linenum)
  261. {
  262. psf_fclose (psf) ;
  263. if (psf_file_valid (psf))
  264. { printf ("nnLine %d: psf->file.filedes should not be valid.nn", linenum) ;
  265. exit (1) ;
  266. } ;
  267. } /* test_close_or_die */
  268. static void
  269. test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
  270. { sf_count_t retval ;
  271. retval = psf_fwrite (data, bytes, items, psf) ;
  272. if (retval != items)
  273. { printf ("nnLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")nn", linenum, retval, items) ;
  274. exit (1) ;
  275. } ;
  276. if ((retval = psf_ftell (psf)) != new_position)
  277. { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")nn", linenum, retval, new_position) ;
  278. exit (1) ;
  279. } ;
  280. return ;
  281. } /* test_write_or_die */
  282. static void
  283. test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
  284. { sf_count_t retval ;
  285. retval = psf_fread (data, bytes, items, psf) ;
  286. if (retval != items)
  287. { printf ("nnLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")nn", linenum, retval, items) ;
  288. exit (1) ;
  289. } ;
  290. if ((retval = psf_ftell (psf)) != new_position)
  291. { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")nn", linenum, retval, new_position) ;
  292. exit (1) ;
  293. } ;
  294. return ;
  295. } /* test_write_or_die */
  296. static void
  297. test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum)
  298. { sf_count_t retval ;
  299. retval = psf_fseek (psf, offset, whence) ;
  300. if (retval != new_position)
  301. { printf ("nnLine %d: psf_fseek() failed. New position is %" PRId64 " (should be %" PRId64 ").nn",
  302. linenum, retval, new_position) ;
  303. exit (1) ;
  304. } ;
  305. } /* test_seek_or_die */
  306. static void
  307. test_equal_or_die (int *array1, int *array2, int len, int linenum)
  308. { int k ;
  309. for (k = 0 ; k < len ; k++)
  310. if (array1 [k] != array2 [k])
  311. printf ("nnLine %d: error at index %d (%d != %d).nn",
  312. linenum, k, array1 [k], array2 [k]) ;
  313. return ;
  314. } /* test_equal_or_die */
  315. static void
  316. make_data (int *data, int len, int seed)
  317. { int k ;
  318. srand (seed * 3333333 + 14756123) ;
  319. for (k = 0 ; k < len ; k++)
  320. data [k] = rand () ;
  321. } /* make_data */
  322. void
  323. test_file_io (void)
  324. { const char *filename = "file_io.dat" ;
  325. file_open_test (filename) ;
  326. file_read_write_test (filename) ;
  327. file_truncate_test (filename) ;
  328. unlink (filename) ;
  329. } /* main */