ports.test 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. ;;;; ports.test --- test suite for Guile I/O ports -*- scheme -*-
  2. ;;;; Jim Blandy <jimb@red-bean.com> --- May 1999
  3. ;;;;
  4. ;;;; Copyright (C) 1999, 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
  5. ;;;;
  6. ;;;; This program is free software; you can redistribute it and/or modify
  7. ;;;; it under the terms of the GNU General Public License as published by
  8. ;;;; the Free Software Foundation; either version 2, or (at your option)
  9. ;;;; any later version.
  10. ;;;;
  11. ;;;; This program is distributed in the hope that it will be useful,
  12. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;;; GNU General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU General Public License
  17. ;;;; along with this software; see the file COPYING. If not, write to
  18. ;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  19. ;;;; Boston, MA 02110-1301 USA
  20. (define-module (test-suite test-ports)
  21. :use-module (test-suite lib)
  22. :use-module (test-suite guile-test)
  23. :use-module (ice-9 popen)
  24. :use-module (ice-9 rdelim))
  25. (define (display-line . args)
  26. (for-each display args)
  27. (newline))
  28. (define (test-file)
  29. (data-file-name "ports-test.tmp"))
  30. ;;;; Some general utilities for testing ports.
  31. ;;; Read from PORT until EOF, and return the result as a string.
  32. (define (read-all port)
  33. (let loop ((chars '()))
  34. (let ((char (read-char port)))
  35. (if (eof-object? char)
  36. (list->string (reverse! chars))
  37. (loop (cons char chars))))))
  38. (define (read-file filename)
  39. (let* ((port (open-input-file filename))
  40. (string (read-all port)))
  41. (close-port port)
  42. string))
  43. ;;;; Normal file ports.
  44. ;;; Write out an s-expression, and read it back.
  45. (let ((string '("From fairest creatures we desire increase,"
  46. "That thereby beauty's rose might never die,"))
  47. (filename (test-file)))
  48. (let ((port (open-output-file filename)))
  49. (write string port)
  50. (close-port port))
  51. (let ((port (open-input-file filename)))
  52. (let ((in-string (read port)))
  53. (pass-if "file: write and read back list of strings"
  54. (equal? string in-string)))
  55. (close-port port))
  56. (delete-file filename))
  57. ;;; Write out a string, and read it back a character at a time.
  58. (let ((string "This is a test string\nwith no newline at the end")
  59. (filename (test-file)))
  60. (let ((port (open-output-file filename)))
  61. (display string port)
  62. (close-port port))
  63. (let ((in-string (read-file filename)))
  64. (pass-if "file: write and read back characters"
  65. (equal? string in-string)))
  66. (delete-file filename))
  67. ;;; Buffered input/output port with seeking.
  68. (let* ((filename (test-file))
  69. (port (open-file filename "w+")))
  70. (display "J'Accuse" port)
  71. (seek port -1 SEEK_CUR)
  72. (pass-if "file: r/w 1"
  73. (char=? (read-char port) #\e))
  74. (pass-if "file: r/w 2"
  75. (eof-object? (read-char port)))
  76. (seek port -1 SEEK_CUR)
  77. (write-char #\x port)
  78. (seek port 7 SEEK_SET)
  79. (pass-if "file: r/w 3"
  80. (char=? (read-char port) #\x))
  81. (seek port -2 SEEK_END)
  82. (pass-if "file: r/w 4"
  83. (char=? (read-char port) #\s))
  84. (close-port port)
  85. (delete-file filename))
  86. ;;; Unbuffered input/output port with seeking.
  87. (let* ((filename (test-file))
  88. (port (open-file filename "w+0")))
  89. (display "J'Accuse" port)
  90. (seek port -1 SEEK_CUR)
  91. (pass-if "file: ub r/w 1"
  92. (char=? (read-char port) #\e))
  93. (pass-if "file: ub r/w 2"
  94. (eof-object? (read-char port)))
  95. (seek port -1 SEEK_CUR)
  96. (write-char #\x port)
  97. (seek port 7 SEEK_SET)
  98. (pass-if "file: ub r/w 3"
  99. (char=? (read-char port) #\x))
  100. (seek port -2 SEEK_END)
  101. (pass-if "file: ub r/w 4"
  102. (char=? (read-char port) #\s))
  103. (close-port port)
  104. (delete-file filename))
  105. ;;; Buffered output-only and input-only ports with seeking.
  106. (let* ((filename (test-file))
  107. (port (open-output-file filename)))
  108. (display "J'Accuse" port)
  109. (pass-if "file: out tell"
  110. (= (seek port 0 SEEK_CUR) 8))
  111. (seek port -1 SEEK_CUR)
  112. (write-char #\x port)
  113. (close-port port)
  114. (let ((iport (open-input-file filename)))
  115. (pass-if "file: in tell 0"
  116. (= (seek iport 0 SEEK_CUR) 0))
  117. (read-char iport)
  118. (pass-if "file: in tell 1"
  119. (= (seek iport 0 SEEK_CUR) 1))
  120. (unread-char #\z iport)
  121. (pass-if "file: in tell 0 after unread"
  122. (= (seek iport 0 SEEK_CUR) 0))
  123. (pass-if "file: unread char still there"
  124. (char=? (read-char iport) #\z))
  125. (seek iport 7 SEEK_SET)
  126. (pass-if "file: in last char"
  127. (char=? (read-char iport) #\x))
  128. (close-port iport))
  129. (delete-file filename))
  130. ;;; unusual characters.
  131. (let* ((filename (test-file))
  132. (port (open-output-file filename)))
  133. (display (string #\nul (integer->char 255) (integer->char 128)
  134. #\nul) port)
  135. (close-port port)
  136. (let* ((port (open-input-file filename))
  137. (line (read-line port)))
  138. (pass-if "file: read back NUL 1"
  139. (char=? (string-ref line 0) #\nul))
  140. (pass-if "file: read back 255"
  141. (char=? (string-ref line 1) (integer->char 255)))
  142. (pass-if "file: read back 128"
  143. (char=? (string-ref line 2) (integer->char 128)))
  144. (pass-if "file: read back NUL 2"
  145. (char=? (string-ref line 3) #\nul))
  146. (pass-if "file: EOF"
  147. (eof-object? (read-char port)))
  148. (close-port port))
  149. (delete-file filename))
  150. ;;; line buffering mode.
  151. (let* ((filename (test-file))
  152. (port (open-file filename "wl"))
  153. (test-string "one line more or less"))
  154. (write-line test-string port)
  155. (let* ((in-port (open-input-file filename))
  156. (line (read-line in-port)))
  157. (close-port in-port)
  158. (close-port port)
  159. (pass-if "file: line buffering"
  160. (string=? line test-string)))
  161. (delete-file filename))
  162. ;;; ungetting characters and strings.
  163. (with-input-from-string "walk on the moon\nmoon"
  164. (lambda ()
  165. (read-char)
  166. (unread-char #\a (current-input-port))
  167. (pass-if "unread-char"
  168. (char=? (read-char) #\a))
  169. (read-line)
  170. (let ((replacenoid "chicken enchilada"))
  171. (unread-char #\newline (current-input-port))
  172. (unread-string replacenoid (current-input-port))
  173. (pass-if "unread-string"
  174. (string=? (read-line) replacenoid)))
  175. (pass-if "unread residue"
  176. (string=? (read-line) "moon"))))
  177. ;;; non-blocking mode on a port. create a pipe and set O_NONBLOCK on
  178. ;;; the reading end. try to read a byte: should get EAGAIN or
  179. ;;; EWOULDBLOCK error.
  180. (let* ((p (pipe))
  181. (r (car p)))
  182. (fcntl r F_SETFL (logior (fcntl r F_GETFL) O_NONBLOCK))
  183. (pass-if "non-blocking-I/O"
  184. (catch 'system-error
  185. (lambda () (read-char r) #f)
  186. (lambda (key . args)
  187. (and (eq? key 'system-error)
  188. (let ((errno (car (list-ref args 3))))
  189. (or (= errno EAGAIN)
  190. (= errno EWOULDBLOCK))))))))
  191. ;;;; Pipe (popen) ports.
  192. ;;; Run a command, and read its output.
  193. (let* ((pipe (open-pipe "echo 'Howdy there, partner!'" "r"))
  194. (in-string (read-all pipe)))
  195. (close-pipe pipe)
  196. (pass-if "pipe: read"
  197. (equal? in-string "Howdy there, partner!\n")))
  198. ;;; Run a command, send some output to it, and see if it worked.
  199. (let* ((filename (test-file))
  200. (pipe (open-pipe (string-append "grep Mommy > " filename) "w")))
  201. (display "Now Jimmy lives on a mushroom cloud\n" pipe)
  202. (display "Mommy, why does everybody have a bomb?\n" pipe)
  203. (close-pipe pipe)
  204. (let ((in-string (read-file filename)))
  205. (pass-if "pipe: write"
  206. (equal? in-string "Mommy, why does everybody have a bomb?\n")))
  207. (delete-file filename))
  208. ;;;; Void ports. These are so trivial we don't test them.
  209. ;;;; String ports.
  210. (with-test-prefix "string ports"
  211. ;; Write text to a string port.
  212. (let* ((string "Howdy there, partner!")
  213. (in-string (call-with-output-string
  214. (lambda (port)
  215. (display string port)
  216. (newline port)))))
  217. (pass-if "display text"
  218. (equal? in-string (string-append string "\n"))))
  219. ;; Write an s-expression to a string port.
  220. (let* ((sexpr '("more utterly random text" 1729 #(a vector) 3.1415926))
  221. (in-sexpr
  222. (call-with-input-string (call-with-output-string
  223. (lambda (port)
  224. (write sexpr port)))
  225. read)))
  226. (pass-if "write/read sexpr"
  227. (equal? in-sexpr sexpr)))
  228. ;; seeking and unreading from an input string.
  229. (let ((text "that text didn't look random to me"))
  230. (call-with-input-string text
  231. (lambda (p)
  232. (pass-if "input tell 0"
  233. (= (seek p 0 SEEK_CUR) 0))
  234. (read-char p)
  235. (pass-if "input tell 1"
  236. (= (seek p 0 SEEK_CUR) 1))
  237. (unread-char #\x p)
  238. (pass-if "input tell back to 0"
  239. (= (seek p 0 SEEK_CUR) 0))
  240. (pass-if "input ungetted char"
  241. (char=? (read-char p) #\x))
  242. (seek p 0 SEEK_END)
  243. (pass-if "input seek to end"
  244. (= (seek p 0 SEEK_CUR)
  245. (string-length text)))
  246. (unread-char #\x p)
  247. (pass-if "input seek to beginning"
  248. (= (seek p 0 SEEK_SET) 0))
  249. (pass-if "input reread first char"
  250. (char=? (read-char p)
  251. (string-ref text 0))))))
  252. ;; seeking an output string.
  253. (let* ((text (string-copy "123456789"))
  254. (len (string-length text))
  255. (result (call-with-output-string
  256. (lambda (p)
  257. (pass-if "output tell 0"
  258. (= (seek p 0 SEEK_CUR) 0))
  259. (display text p)
  260. (pass-if "output tell end"
  261. (= (seek p 0 SEEK_CUR) len))
  262. (pass-if "output seek to beginning"
  263. (= (seek p 0 SEEK_SET) 0))
  264. (write-char #\a p)
  265. (seek p -1 SEEK_END)
  266. (pass-if "output seek to last char"
  267. (= (seek p 0 SEEK_CUR)
  268. (- len 1)))
  269. (write-char #\b p)))))
  270. (string-set! text 0 #\a)
  271. (string-set! text (- len 1) #\b)
  272. (pass-if "output check"
  273. (string=? text result))))
  274. (with-test-prefix "call-with-output-string"
  275. ;; In Guile 1.6.4, closing the port resulted in a segv, check that doesn't
  276. ;; occur.
  277. (pass-if-exception "proc closes port" exception:wrong-type-arg
  278. (call-with-output-string close-port)))
  279. ;;;; Soft ports. No tests implemented yet.
  280. ;;;; Generic operations across all port types.
  281. (let ((port-loop-temp (test-file)))
  282. ;; Return a list of input ports that all return the same text.
  283. ;; We map tests over this list.
  284. (define (input-port-list text)
  285. ;; Create a text file some of the ports will use.
  286. (let ((out-port (open-output-file port-loop-temp)))
  287. (display text out-port)
  288. (close-port out-port))
  289. (list (open-input-file port-loop-temp)
  290. (open-input-pipe (string-append "cat " port-loop-temp))
  291. (call-with-input-string text (lambda (x) x))
  292. ;; We don't test soft ports at the moment.
  293. ))
  294. (define port-list-names '("file" "pipe" "string"))
  295. ;; Test the line counter.
  296. (define (test-line-counter text second-line final-column)
  297. (with-test-prefix "line counter"
  298. (let ((ports (input-port-list text)))
  299. (for-each
  300. (lambda (port port-name)
  301. (with-test-prefix port-name
  302. (pass-if "at beginning of input"
  303. (= (port-line port) 0))
  304. (pass-if "read first character"
  305. (eqv? (read-char port) #\x))
  306. (pass-if "after reading one character"
  307. (= (port-line port) 0))
  308. (pass-if "read first newline"
  309. (eqv? (read-char port) #\newline))
  310. (pass-if "after reading first newline char"
  311. (= (port-line port) 1))
  312. (pass-if "second line read correctly"
  313. (equal? (read-line port) second-line))
  314. (pass-if "read-line increments line number"
  315. (= (port-line port) 2))
  316. (pass-if "read-line returns EOF"
  317. (let loop ((i 0))
  318. (cond
  319. ((eof-object? (read-line port)) #t)
  320. ((> i 20) #f)
  321. (else (loop (+ i 1))))))
  322. (pass-if "line count is 5 at EOF"
  323. (= (port-line port) 5))
  324. (pass-if "column is correct at EOF"
  325. (= (port-column port) final-column))))
  326. ports port-list-names)
  327. (for-each close-port ports)
  328. (delete-file port-loop-temp))))
  329. (with-test-prefix "newline"
  330. (test-line-counter
  331. (string-append "x\n"
  332. "He who receives an idea from me, receives instruction\n"
  333. "himself without lessening mine; as he who lights his\n"
  334. "taper at mine, receives light without darkening me.\n"
  335. " --- Thomas Jefferson\n")
  336. "He who receives an idea from me, receives instruction"
  337. 0))
  338. (with-test-prefix "no newline"
  339. (test-line-counter
  340. (string-append "x\n"
  341. "He who receives an idea from me, receives instruction\n"
  342. "himself without lessening mine; as he who lights his\n"
  343. "taper at mine, receives light without darkening me.\n"
  344. " --- Thomas Jefferson\n"
  345. "no newline here")
  346. "He who receives an idea from me, receives instruction"
  347. 15)))
  348. ;; Test port-line and port-column for output ports
  349. (define (test-output-line-counter text final-column)
  350. (with-test-prefix "port-line and port-column for output ports"
  351. (let ((port (open-output-string)))
  352. (pass-if "at beginning of input"
  353. (and (= (port-line port) 0)
  354. (= (port-column port) 0)))
  355. (write-char #\x port)
  356. (pass-if "after writing one character"
  357. (and (= (port-line port) 0)
  358. (= (port-column port) 1)))
  359. (write-char #\newline port)
  360. (pass-if "after writing first newline char"
  361. (and (= (port-line port) 1)
  362. (= (port-column port) 0)))
  363. (display text port)
  364. (pass-if "line count is 5 at end"
  365. (= (port-line port) 5))
  366. (pass-if "column is correct at end"
  367. (= (port-column port) final-column)))))
  368. (test-output-line-counter
  369. (string-append "He who receives an idea from me, receives instruction\n"
  370. "himself without lessening mine; as he who lights his\n"
  371. "taper at mine, receives light without darkening me.\n"
  372. " --- Thomas Jefferson\n"
  373. "no newline here")
  374. 15)
  375. (with-test-prefix "port-column"
  376. (with-test-prefix "output"
  377. (pass-if "x"
  378. (let ((port (open-output-string)))
  379. (display "x" port)
  380. (= 1 (port-column port))))
  381. (pass-if "\\a"
  382. (let ((port (open-output-string)))
  383. (display "\a" port)
  384. (= 0 (port-column port))))
  385. (pass-if "x\\a"
  386. (let ((port (open-output-string)))
  387. (display "x\a" port)
  388. (= 1 (port-column port))))
  389. (pass-if "\\x08 backspace"
  390. (let ((port (open-output-string)))
  391. (display "\x08" port)
  392. (= 0 (port-column port))))
  393. (pass-if "x\\x08 backspace"
  394. (let ((port (open-output-string)))
  395. (display "x\x08" port)
  396. (= 0 (port-column port))))
  397. (pass-if "\\n"
  398. (let ((port (open-output-string)))
  399. (display "\n" port)
  400. (= 0 (port-column port))))
  401. (pass-if "x\\n"
  402. (let ((port (open-output-string)))
  403. (display "x\n" port)
  404. (= 0 (port-column port))))
  405. (pass-if "\\r"
  406. (let ((port (open-output-string)))
  407. (display "\r" port)
  408. (= 0 (port-column port))))
  409. (pass-if "x\\r"
  410. (let ((port (open-output-string)))
  411. (display "x\r" port)
  412. (= 0 (port-column port))))
  413. (pass-if "\\t"
  414. (let ((port (open-output-string)))
  415. (display "\t" port)
  416. (= 8 (port-column port))))
  417. (pass-if "x\\t"
  418. (let ((port (open-output-string)))
  419. (display "x\t" port)
  420. (= 8 (port-column port)))))
  421. (with-test-prefix "input"
  422. (pass-if "x"
  423. (let ((port (open-input-string "x")))
  424. (while (not (eof-object? (read-char port))))
  425. (= 1 (port-column port))))
  426. (pass-if "\\a"
  427. (let ((port (open-input-string "\a")))
  428. (while (not (eof-object? (read-char port))))
  429. (= 0 (port-column port))))
  430. (pass-if "x\\a"
  431. (let ((port (open-input-string "x\a")))
  432. (while (not (eof-object? (read-char port))))
  433. (= 1 (port-column port))))
  434. (pass-if "\\x08 backspace"
  435. (let ((port (open-input-string "\x08")))
  436. (while (not (eof-object? (read-char port))))
  437. (= 0 (port-column port))))
  438. (pass-if "x\\x08 backspace"
  439. (let ((port (open-input-string "x\x08")))
  440. (while (not (eof-object? (read-char port))))
  441. (= 0 (port-column port))))
  442. (pass-if "\\n"
  443. (let ((port (open-input-string "\n")))
  444. (while (not (eof-object? (read-char port))))
  445. (= 0 (port-column port))))
  446. (pass-if "x\\n"
  447. (let ((port (open-input-string "x\n")))
  448. (while (not (eof-object? (read-char port))))
  449. (= 0 (port-column port))))
  450. (pass-if "\\r"
  451. (let ((port (open-input-string "\r")))
  452. (while (not (eof-object? (read-char port))))
  453. (= 0 (port-column port))))
  454. (pass-if "x\\r"
  455. (let ((port (open-input-string "x\r")))
  456. (while (not (eof-object? (read-char port))))
  457. (= 0 (port-column port))))
  458. (pass-if "\\t"
  459. (let ((port (open-input-string "\t")))
  460. (while (not (eof-object? (read-char port))))
  461. (= 8 (port-column port))))
  462. (pass-if "x\\t"
  463. (let ((port (open-input-string "x\t")))
  464. (while (not (eof-object? (read-char port))))
  465. (= 8 (port-column port))))))
  466. (with-test-prefix "port-line"
  467. ;; in guile 1.8.1 and earlier port-line was truncated to an int, whereas
  468. ;; scm_t_port actually holds a long; this restricted the range on 64-bit
  469. ;; systems
  470. (pass-if "set most-positive-fixnum/2"
  471. (let ((n (quotient most-positive-fixnum 2))
  472. (port (open-output-string)))
  473. (set-port-line! port n)
  474. (eqv? n (port-line port)))))
  475. ;;;
  476. ;;; port-for-each
  477. ;;;
  478. (with-test-prefix "port-for-each"
  479. ;; In guile 1.8.0 through 1.8.2, port-for-each could pass a freed cell to
  480. ;; its iterator func if a port was inaccessible in the last gc mark but
  481. ;; the lazy sweeping has not yet reached it to remove it from the port
  482. ;; table (scm_i_port_table). Provoking those gc conditions is a little
  483. ;; tricky, but the following code made it happen in 1.8.2.
  484. (pass-if "passing freed cell"
  485. (throw 'unresolved)
  486. (let ((lst '()))
  487. ;; clear out the heap
  488. (gc) (gc) (gc)
  489. ;; allocate cells so the opened ports aren't at the start of the heap
  490. (make-list 1000)
  491. (open-input-file "/dev/null")
  492. (make-list 1000)
  493. (open-input-file "/dev/null")
  494. ;; this gc leaves the above ports unmarked, ie. inaccessible
  495. (gc)
  496. ;; but they're still in the port table, so this sees them
  497. (port-for-each (lambda (port)
  498. (set! lst (cons port lst))))
  499. ;; this forces completion of the sweeping
  500. (gc) (gc) (gc)
  501. ;; and (if the bug is present) the cells accumulated in LST are now
  502. ;; freed cells, which give #f from `port?'
  503. (not (memq #f (map port? lst))))))
  504. ;;;
  505. ;;; seek
  506. ;;;
  507. (with-test-prefix "seek"
  508. (with-test-prefix "file port"
  509. (pass-if "SEEK_CUR"
  510. (call-with-output-file (test-file)
  511. (lambda (port)
  512. (display "abcde" port)))
  513. (let ((port (open-file (test-file) "r")))
  514. (read-char port)
  515. (seek port 2 SEEK_CUR)
  516. (eqv? #\d (read-char port))))
  517. (pass-if "SEEK_SET"
  518. (call-with-output-file (test-file)
  519. (lambda (port)
  520. (display "abcde" port)))
  521. (let ((port (open-file (test-file) "r")))
  522. (read-char port)
  523. (seek port 3 SEEK_SET)
  524. (eqv? #\d (read-char port))))
  525. (pass-if "SEEK_END"
  526. (call-with-output-file (test-file)
  527. (lambda (port)
  528. (display "abcde" port)))
  529. (let ((port (open-file (test-file) "r")))
  530. (read-char port)
  531. (seek port -2 SEEK_END)
  532. (eqv? #\d (read-char port))))))
  533. ;;;
  534. ;;; truncate-file
  535. ;;;
  536. (with-test-prefix "truncate-file"
  537. (pass-if-exception "flonum file" exception:wrong-type-arg
  538. (truncate-file 1.0 123))
  539. (pass-if-exception "frac file" exception:wrong-type-arg
  540. (truncate-file 7/3 123))
  541. (with-test-prefix "filename"
  542. (pass-if-exception "flonum length" exception:wrong-type-arg
  543. (call-with-output-file (test-file)
  544. (lambda (port)
  545. (display "hello" port)))
  546. (truncate-file (test-file) 1.0))
  547. (pass-if "shorten"
  548. (call-with-output-file (test-file)
  549. (lambda (port)
  550. (display "hello" port)))
  551. (truncate-file (test-file) 1)
  552. (eqv? 1 (stat:size (stat (test-file)))))
  553. (pass-if-exception "shorten to current pos" exception:miscellaneous-error
  554. (call-with-output-file (test-file)
  555. (lambda (port)
  556. (display "hello" port)))
  557. (truncate-file (test-file))))
  558. (with-test-prefix "file descriptor"
  559. (pass-if "shorten"
  560. (call-with-output-file (test-file)
  561. (lambda (port)
  562. (display "hello" port)))
  563. (let ((fd (open-fdes (test-file) O_RDWR)))
  564. (truncate-file fd 1)
  565. (close-fdes fd))
  566. (eqv? 1 (stat:size (stat (test-file)))))
  567. (pass-if "shorten to current pos"
  568. (call-with-output-file (test-file)
  569. (lambda (port)
  570. (display "hello" port)))
  571. (let ((fd (open-fdes (test-file) O_RDWR)))
  572. (seek fd 1 SEEK_SET)
  573. (truncate-file fd)
  574. (close-fdes fd))
  575. (eqv? 1 (stat:size (stat (test-file))))))
  576. (with-test-prefix "file port"
  577. (pass-if "shorten"
  578. (call-with-output-file (test-file)
  579. (lambda (port)
  580. (display "hello" port)))
  581. (let ((port (open-file (test-file) "r+")))
  582. (truncate-file port 1))
  583. (eqv? 1 (stat:size (stat (test-file)))))
  584. (pass-if "shorten to current pos"
  585. (call-with-output-file (test-file)
  586. (lambda (port)
  587. (display "hello" port)))
  588. (let ((port (open-file (test-file) "r+")))
  589. (read-char port)
  590. (truncate-file port))
  591. (eqv? 1 (stat:size (stat (test-file)))))))
  592. ;;;; testing read-delimited and friends
  593. (with-test-prefix "read-delimited!"
  594. (let ((c (make-string 20 #\!)))
  595. (call-with-input-string
  596. "defdef\nghighi\n"
  597. (lambda (port)
  598. (read-delimited! "\n" c port 'concat)
  599. (pass-if "read-delimited! reads a first line"
  600. (string=? c "defdef\n!!!!!!!!!!!!!"))
  601. (read-delimited! "\n" c port 'concat 3)
  602. (pass-if "read-delimited! reads a first line"
  603. (string=? c "defghighi\n!!!!!!!!!!"))))))
  604. ;;;; char-ready?
  605. (call-with-input-string
  606. "howdy"
  607. (lambda (port)
  608. (pass-if "char-ready? returns true on string port"
  609. (char-ready? port))))
  610. ;;; This segfaults on some versions of Guile. We really should run
  611. ;;; the tests in a subprocess...
  612. (call-with-input-string
  613. "howdy"
  614. (lambda (port)
  615. (with-input-from-port
  616. port
  617. (lambda ()
  618. (pass-if "char-ready? returns true on string port as default port"
  619. (char-ready?))))))
  620. ;;;; Close current-input-port, and make sure everyone can handle it.
  621. (with-test-prefix "closing current-input-port"
  622. (for-each (lambda (procedure name)
  623. (with-input-from-port
  624. (call-with-input-string "foo" (lambda (p) p))
  625. (lambda ()
  626. (close-port (current-input-port))
  627. (pass-if-exception name
  628. exception:wrong-type-arg
  629. (procedure)))))
  630. (list read read-char read-line)
  631. '("read" "read-char" "read-line")))
  632. (delete-file (test-file))