pipe_test.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /*
  2. ** Copyright (C) 2001-2011 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 General Public License as published by
  6. ** the Free Software Foundation; either version 2 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 General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. /*==========================================================================
  19. ** This is a test program which tests reading from and writing to pipes.
  20. */
  21. #include "sfconfig.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #if (OS_IS_WIN32 || HAVE_PIPE == 0 || HAVE_WAITPID == 0)
  26. int
  27. main (void)
  28. {
  29. puts (" pipe_test : this test doesn't work on this OS.") ;
  30. return 0 ;
  31. } /* main */
  32. #else
  33. #if HAVE_UNISTD_H
  34. #include <unistd.h>
  35. #endif
  36. #include <errno.h>
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <sys/wait.h>
  40. #include <sndfile.h>
  41. #include "utils.h"
  42. typedef struct
  43. { int format ;
  44. const char *ext ;
  45. } FILETYPE ;
  46. static int file_exists (const char *filename) ;
  47. static void useek_pipe_rw_test (int filetype, const char *ext) ;
  48. static void pipe_read_test (int filetype, const char *ext) ;
  49. static void pipe_write_test (const char *ext) ;
  50. static void pipe_test_others (FILETYPE*, FILETYPE*) ;
  51. static FILETYPE read_write_types [] =
  52. { { SF_FORMAT_RAW , "raw" },
  53. { SF_FORMAT_AU , "au" },
  54. /* Lite remove start */
  55. { SF_FORMAT_PAF , "paf" },
  56. { SF_FORMAT_IRCAM , "ircam" },
  57. { SF_FORMAT_PVF , "pvf" },
  58. /* Lite remove end */
  59. { 0 , NULL }
  60. } ;
  61. static FILETYPE read_only_types [] =
  62. { { SF_FORMAT_RAW , "raw" },
  63. { SF_FORMAT_AU , "au" },
  64. { SF_FORMAT_AIFF , "aiff" },
  65. { SF_FORMAT_WAV , "wav" },
  66. { SF_FORMAT_W64 , "w64" },
  67. /* Lite remove start */
  68. { SF_FORMAT_PAF , "paf" },
  69. { SF_FORMAT_NIST , "nist" },
  70. { SF_FORMAT_IRCAM , "ircam" },
  71. { SF_FORMAT_MAT4 , "mat4" },
  72. { SF_FORMAT_MAT5 , "mat5" },
  73. { SF_FORMAT_SVX , "svx" },
  74. { SF_FORMAT_PVF , "pvf" },
  75. /* Lite remove end */
  76. { 0 , NULL }
  77. } ;
  78. int
  79. main (void)
  80. { int k ;
  81. if (file_exists ("libsndfile.spec.in"))
  82. exit_if_true (chdir ("tests") != 0, "\n Error : chdir ('tests') failed.\n") ;
  83. for (k = 0 ; read_only_types [k].format ; k++)
  84. pipe_read_test (read_only_types [k].format, read_only_types [k].ext) ;
  85. for (k = 0 ; read_write_types [k].format ; k++)
  86. pipe_write_test (read_write_types [k].ext) ;
  87. for (k = 0 ; read_write_types [k].format ; k++)
  88. useek_pipe_rw_test (read_write_types [k].format, read_write_types [k].ext) ;
  89. if (0)
  90. pipe_test_others (read_write_types, read_only_types) ;
  91. return 0 ;
  92. } /* main */
  93. /*==============================================================================
  94. */
  95. static void
  96. pipe_read_test (int filetype, const char *ext)
  97. { static short data [PIPE_TEST_LEN] ;
  98. static char buffer [256] ;
  99. static char filename [256] ;
  100. SNDFILE *outfile ;
  101. SF_INFO sfinfo ;
  102. int k, retval ;
  103. snprintf (filename, sizeof (filename), "pipe_in.%s", ext) ;
  104. print_test_name ("pipe_read_test", filename) ;
  105. sfinfo.format = filetype | SF_FORMAT_PCM_16 ;
  106. sfinfo.channels = 1 ;
  107. sfinfo.samplerate = 44100 ;
  108. for (k = 0 ; k < PIPE_TEST_LEN ; k++)
  109. data [k] = PIPE_INDEX (k) ;
  110. outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
  111. test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
  112. sf_close (outfile) ;
  113. snprintf (buffer, sizeof (buffer), "cat %s | ./stdin_test %s ", filename, ext) ;
  114. if ((retval = system (buffer)) != 0)
  115. { retval = WEXITSTATUS (retval) ;
  116. printf ("\n\n Line %d : pipe test returned error for file type \"%s\".\n\n", __LINE__, ext) ;
  117. exit (retval) ;
  118. } ;
  119. unlink (filename) ;
  120. puts ("ok") ;
  121. return ;
  122. } /* pipe_read_test */
  123. static void
  124. pipe_write_test (const char *ext)
  125. { static char buffer [256] ;
  126. int retval ;
  127. print_test_name ("pipe_write_test", ext) ;
  128. snprintf (buffer, sizeof (buffer), "./stdout_test %s | ./stdin_test %s ", ext, ext) ;
  129. if ((retval = system (buffer)))
  130. { retval = WEXITSTATUS (retval) ;
  131. printf ("\n\n Line %d : pipe test returned error file type \"%s\".\n\n", __LINE__, ext) ;
  132. exit (retval) ;
  133. } ;
  134. puts ("ok") ;
  135. return ;
  136. } /* pipe_write_test */
  137. /*==============================================================================
  138. */
  139. static void
  140. useek_pipe_rw_short (const char * ext, SF_INFO * psfinfo_write, SF_INFO * psfinfo_read)
  141. { static short buffer [PIPE_TEST_LEN] ;
  142. static short data [PIPE_TEST_LEN] ;
  143. SNDFILE *outfile ;
  144. SNDFILE *infile_piped ;
  145. int k, status = 0 ;
  146. int pipefd [2] ;
  147. pid_t pida ;
  148. for (k = 0 ; k < PIPE_TEST_LEN ; k++)
  149. data [k] = PIPE_INDEX (k) ;
  150. /*
  151. ** Create the pipe.
  152. */
  153. exit_if_true (pipe (pipefd) != 0, "\n\n%s %d : pipe failed : %s\n", __func__, __LINE__, strerror (errno)) ;
  154. /*
  155. ** Attach the write end of the pipe to be written to.
  156. */
  157. if ((outfile = sf_open_fd (pipefd [1], SFM_WRITE, psfinfo_write, SF_TRUE)) == NULL)
  158. { printf ("\n\n%s %d : unable to create unseekable pipe for write type \"%s\".\n", __func__, __LINE__, ext) ;
  159. printf ("\t%s\n\n", sf_strerror (outfile)) ;
  160. exit (1) ;
  161. } ;
  162. if (sf_error (outfile) != SF_ERR_NO_ERROR)
  163. { printf ("\n\n%s %d : unable to open unseekable pipe for write type \"%s\".\n\n", __func__, __LINE__, ext) ;
  164. exit (1) ;
  165. } ;
  166. /*
  167. ** Attach the read end of the pipe to be read from.
  168. */
  169. if ((infile_piped = sf_open_fd (pipefd [0], SFM_READ, psfinfo_read, SF_TRUE)) == NULL)
  170. { printf ("\n\n%s %d : unable to create unseekable pipe for read type. \"%s\".\n\n", __func__, __LINE__, ext) ;
  171. exit (1) ;
  172. } ;
  173. if (sf_error (infile_piped) != SF_ERR_NO_ERROR)
  174. { printf ("\n\n%s %d : unable to open unseekable pipe for read type \"%s\".\n\n", __func__, __LINE__, ext) ;
  175. exit (1) ;
  176. } ;
  177. /* Fork a child process that will write directly into the pipe. */
  178. if ((pida = fork ()) == 0) /* child process */
  179. { test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
  180. exit (0) ;
  181. } ;
  182. /* In the parent process, read from the pipe and compare what is read
  183. ** to what is written, if they match everything went as planned.
  184. */
  185. test_readf_short_or_die (infile_piped, 0, buffer, PIPE_TEST_LEN, __LINE__) ;
  186. if (memcmp (buffer, data, sizeof (buffer)) != 0)
  187. { printf ("\n\n%s %d : unseekable pipe test failed for file type \"%s\".\n\n", __func__, __LINE__, ext) ;
  188. exit (1) ;
  189. } ;
  190. /* Wait for the child process to return. */
  191. waitpid (pida, &status, 0) ;
  192. status = WEXITSTATUS (status) ;
  193. sf_close (outfile) ;
  194. sf_close (infile_piped) ;
  195. if (status != 0)
  196. { printf ("\n\n%s %d : status of child process is %d for file type %s.\n\n", __func__, __LINE__, status, ext) ;
  197. exit (1) ;
  198. } ;
  199. return ;
  200. } /* useek_pipe_rw_short */
  201. static void
  202. useek_pipe_rw_float (const char * ext, SF_INFO * psfinfo_write, SF_INFO * psfinfo_read)
  203. { static float buffer [PIPE_TEST_LEN] ;
  204. static float data [PIPE_TEST_LEN] ;
  205. SNDFILE *outfile ;
  206. SNDFILE *infile_piped ;
  207. int k, status = 0 ;
  208. int pipefd [2] ;
  209. pid_t pida ;
  210. for (k = 0 ; k < PIPE_TEST_LEN ; k++)
  211. data [k] = PIPE_INDEX (k) ;
  212. /*
  213. ** Create the pipe.
  214. */
  215. exit_if_true (pipe (pipefd) != 0, "\n\n%s %d : pipe failed : %s\n", __func__, __LINE__, strerror (errno)) ;
  216. /*
  217. ** Attach the write end of the pipe to be written to.
  218. */
  219. if ((outfile = sf_open_fd (pipefd [1], SFM_WRITE, psfinfo_write, SF_TRUE)) == NULL)
  220. { printf ("\n\n%s %d : unable to create unseekable pipe for write type \"%s\".\n", __func__, __LINE__, ext) ;
  221. printf ("\t%s\n\n", sf_strerror (outfile)) ;
  222. exit (1) ;
  223. } ;
  224. if (sf_error (outfile) != SF_ERR_NO_ERROR)
  225. { printf ("\n\n%s %d : unable to open unseekable pipe for write type \"%s\".\n\n", __func__, __LINE__, ext) ;
  226. exit (1) ;
  227. } ;
  228. /*
  229. ** Attach the read end of the pipe to be read from.
  230. */
  231. if ((infile_piped = sf_open_fd (pipefd [0], SFM_READ, psfinfo_read, SF_TRUE)) == NULL)
  232. { printf ("\n\n%s %d : unable to create unseekable pipe for read type. \"%s\".\n\n", __func__, __LINE__, ext) ;
  233. exit (1) ;
  234. } ;
  235. if (sf_error (infile_piped) != SF_ERR_NO_ERROR)
  236. { printf ("\n\n%s %d : unable to open unseekable pipe for read type \"%s\".\n\n", __func__, __LINE__, ext) ;
  237. exit (1) ;
  238. } ;
  239. /* Fork a child process that will write directly into the pipe. */
  240. if ((pida = fork ()) == 0) /* child process */
  241. { test_writef_float_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
  242. exit (0) ;
  243. } ;
  244. /* In the parent process, read from the pipe and compare what is read
  245. ** to what is written, if they match everything went as planned.
  246. */
  247. test_readf_float_or_die (infile_piped, 0, buffer, PIPE_TEST_LEN, __LINE__) ;
  248. if (memcmp (buffer, data, sizeof (buffer)) != 0)
  249. { printf ("\n\n%s %d : unseekable pipe test failed for file type \"%s\".\n\n", __func__, __LINE__, ext) ;
  250. exit (1) ;
  251. } ;
  252. /* Wait for the child process to return. */
  253. waitpid (pida, &status, 0) ;
  254. status = WEXITSTATUS (status) ;
  255. sf_close (outfile) ;
  256. sf_close (infile_piped) ;
  257. if (status != 0)
  258. { printf ("\n\n%s %d : status of child process is %d for file type %s.\n\n", __func__, __LINE__, status, ext) ;
  259. exit (1) ;
  260. } ;
  261. return ;
  262. } /* useek_pipe_rw_float */
  263. static void
  264. useek_pipe_rw_double (const char * ext, SF_INFO * psfinfo_write, SF_INFO * psfinfo_read)
  265. { static double buffer [PIPE_TEST_LEN] ;
  266. static double data [PIPE_TEST_LEN] ;
  267. SNDFILE *outfile ;
  268. SNDFILE *infile_piped ;
  269. int k, status = 0 ;
  270. int pipefd [2] ;
  271. pid_t pida ;
  272. for (k = 0 ; k < PIPE_TEST_LEN ; k++)
  273. data [k] = PIPE_INDEX (k) ;
  274. /*
  275. ** Create the pipe.
  276. */
  277. exit_if_true (pipe (pipefd) != 0, "\n\n%s %d : pipe failed : %s\n", __func__, __LINE__, strerror (errno)) ;
  278. /*
  279. ** Attach the write end of the pipe to be written to.
  280. */
  281. if ((outfile = sf_open_fd (pipefd [1], SFM_WRITE, psfinfo_write, SF_TRUE)) == NULL)
  282. { printf ("\n\n%s %d : unable to create unseekable pipe for write type \"%s\".\n", __func__, __LINE__, ext) ;
  283. printf ("\t%s\n\n", sf_strerror (outfile)) ;
  284. exit (1) ;
  285. } ;
  286. if (sf_error (outfile) != SF_ERR_NO_ERROR)
  287. { printf ("\n\n%s %d : unable to open unseekable pipe for write type \"%s\".\n\n", __func__, __LINE__, ext) ;
  288. exit (1) ;
  289. } ;
  290. /*
  291. ** Attach the read end of the pipe to be read from.
  292. */
  293. if ((infile_piped = sf_open_fd (pipefd [0], SFM_READ, psfinfo_read, SF_TRUE)) == NULL)
  294. { printf ("\n\n%s %d : unable to create unseekable pipe for read type. \"%s\".\n\n", __func__, __LINE__, ext) ;
  295. exit (1) ;
  296. } ;
  297. if (sf_error (infile_piped) != SF_ERR_NO_ERROR)
  298. { printf ("\n\n%s %d : unable to open unseekable pipe for read type \"%s\".\n\n", __func__, __LINE__, ext) ;
  299. exit (1) ;
  300. } ;
  301. /* Fork a child process that will write directly into the pipe. */
  302. if ((pida = fork ()) == 0) /* child process */
  303. { test_writef_double_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
  304. exit (0) ;
  305. } ;
  306. /* In the parent process, read from the pipe and compare what is read
  307. ** to what is written, if they match everything went as planned.
  308. */
  309. test_readf_double_or_die (infile_piped, 0, buffer, PIPE_TEST_LEN, __LINE__) ;
  310. if (memcmp (buffer, data, sizeof (buffer)) != 0)
  311. { printf ("\n\n%s %d : unseekable pipe test failed for file type \"%s\".\n\n", __func__, __LINE__, ext) ;
  312. exit (1) ;
  313. } ;
  314. /* Wait for the child process to return. */
  315. waitpid (pida, &status, 0) ;
  316. status = WEXITSTATUS (status) ;
  317. sf_close (outfile) ;
  318. sf_close (infile_piped) ;
  319. if (status != 0)
  320. { printf ("\n\n%s %d : status of child process is %d for file type %s.\n\n", __func__, __LINE__, status, ext) ;
  321. exit (1) ;
  322. } ;
  323. return ;
  324. } /* useek_pipe_rw_double */
  325. static void
  326. useek_pipe_rw_test (int filetype, const char *ext)
  327. { SF_INFO sfinfo_write ;
  328. SF_INFO sfinfo_read ;
  329. print_test_name ("useek_pipe_rw_test", ext) ;
  330. /*
  331. ** Setup the INFO structures for the filetype we will be
  332. ** working with.
  333. */
  334. sfinfo_write.format = filetype | SF_FORMAT_PCM_16 ;
  335. sfinfo_write.channels = 1 ;
  336. sfinfo_write.samplerate = 44100 ;
  337. sfinfo_read.format = 0 ;
  338. if (filetype == SF_FORMAT_RAW)
  339. { sfinfo_read.format = filetype | SF_FORMAT_PCM_16 ;
  340. sfinfo_read.channels = 1 ;
  341. sfinfo_read.samplerate = 44100 ;
  342. } ;
  343. useek_pipe_rw_short (ext, &sfinfo_write, &sfinfo_read) ;
  344. sfinfo_read.format = sfinfo_write.format = filetype | SF_FORMAT_FLOAT ;
  345. if (sf_format_check (&sfinfo_read) != 0)
  346. useek_pipe_rw_float (ext, &sfinfo_write, &sfinfo_read) ;
  347. sfinfo_read.format = sfinfo_write.format = filetype | SF_FORMAT_DOUBLE ;
  348. if (sf_format_check (&sfinfo_read) != 0)
  349. useek_pipe_rw_double (ext, &sfinfo_write, &sfinfo_read) ;
  350. puts ("ok") ;
  351. return ;
  352. } /* useek_pipe_rw_test */
  353. static void
  354. pipe_test_others (FILETYPE* list1, FILETYPE* list2)
  355. { SF_FORMAT_INFO info ;
  356. int k, m, major_count, in_list ;
  357. print_test_name ("pipe_test_others", "") ;
  358. sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int)) ;
  359. for (k = 0 ; k < major_count ; k++)
  360. { info.format = k ;
  361. sf_command (NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof (info)) ;
  362. in_list = SF_FALSE ;
  363. for (m = 0 ; list1 [m].format ; m++)
  364. if (info.format == list1 [m].format)
  365. in_list = SF_TRUE ;
  366. for (m = 0 ; list2 [m].format ; m++)
  367. if (info.format == list2 [m].format)
  368. in_list = SF_TRUE ;
  369. if (in_list)
  370. continue ;
  371. printf ("%s %x\n", info.name, info.format) ;
  372. if (1)
  373. { static short data [PIPE_TEST_LEN] ;
  374. static char buffer [256] ;
  375. static const char *filename = "pipe_in.dat" ;
  376. SNDFILE *outfile ;
  377. SF_INFO sfinfo ;
  378. int retval ;
  379. sfinfo.format = info.format | SF_FORMAT_PCM_16 ;
  380. sfinfo.channels = 1 ;
  381. sfinfo.samplerate = 44100 ;
  382. outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
  383. test_writef_short_or_die (outfile, 0, data, PIPE_TEST_LEN, __LINE__) ;
  384. sf_close (outfile) ;
  385. snprintf (buffer, sizeof (buffer), "cat %s | ./stdin_test %s %d ", filename, info.extension, PIPE_TEST_LEN) ;
  386. if ((retval = system (buffer)) == 0)
  387. { retval = WEXITSTATUS (retval) ;
  388. printf ("\n\n Line %d : pipe test should have returned error file type \"%s\" but didn't.\n\n", __LINE__, info.name) ;
  389. exit (1) ;
  390. } ;
  391. unlink (filename) ;
  392. } ;
  393. } ;
  394. puts ("ok") ;
  395. return ;
  396. } /* pipe_test_others */
  397. /*==============================================================================
  398. */
  399. static int
  400. file_exists (const char *filename)
  401. { struct stat buf ;
  402. if (stat (filename, &buf))
  403. return 0 ;
  404. return 1 ;
  405. } /* file_exists */
  406. #endif