socket.test 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. ;;;; socket.test --- test socket functions -*- scheme -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010,
  4. ;;;; 2011 Free Software Foundation, Inc.
  5. ;;;;
  6. ;;;; This library is free software; you can redistribute it and/or
  7. ;;;; modify it under the terms of the GNU Lesser General Public
  8. ;;;; License as published by the Free Software Foundation; either
  9. ;;;; version 3 of the License, or (at your option) any later version.
  10. ;;;;
  11. ;;;; This library 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 GNU
  14. ;;;; Lesser General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU Lesser General Public
  17. ;;;; License along with this library; if not, write to the Free Software
  18. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. (define-module (test-suite test-socket)
  20. #:use-module (rnrs bytevectors)
  21. #:use-module (srfi srfi-26)
  22. #:use-module (test-suite lib))
  23. ;;;
  24. ;;; htonl
  25. ;;;
  26. (if (defined? 'htonl)
  27. (with-test-prefix "htonl"
  28. (pass-if "0" (eqv? 0 (htonl 0)))
  29. (pass-if-exception "-1" exception:out-of-range
  30. (htonl -1))
  31. ;; prior to guile 1.6.9 and 1.8.1, systems with 64-bit longs didn't detect
  32. ;; an overflow for values 2^32 <= x < 2^63
  33. (pass-if-exception "2^32" exception:out-of-range
  34. (htonl (ash 1 32)))
  35. (pass-if-exception "2^1024" exception:out-of-range
  36. (htonl (ash 1 1024)))))
  37. ;;;
  38. ;;; inet-ntop
  39. ;;;
  40. (if (defined? 'inet-ntop)
  41. (with-test-prefix "inet-ntop"
  42. (with-test-prefix "ipv6"
  43. (pass-if "0"
  44. (string? (inet-ntop AF_INET6 0)))
  45. (pass-if "2^128-1"
  46. (string? (inet-ntop AF_INET6 (1- (ash 1 128)))))
  47. (pass-if-exception "-1" exception:out-of-range
  48. (inet-ntop AF_INET6 -1))
  49. (pass-if-exception "2^128" exception:out-of-range
  50. (inet-ntop AF_INET6 (ash 1 128)))
  51. (pass-if-exception "2^1024" exception:out-of-range
  52. (inet-ntop AF_INET6 (ash 1 1024))))))
  53. ;;;
  54. ;;; inet-pton
  55. ;;;
  56. (if (defined? 'inet-pton)
  57. (with-test-prefix "inet-pton"
  58. (with-test-prefix "ipv6"
  59. (pass-if "00:00:00:00:00:00:00:00"
  60. (eqv? 0 (inet-pton AF_INET6 "00:00:00:00:00:00:00:00")))
  61. (pass-if "0:0:0:0:0:0:0:1"
  62. (eqv? 1 (inet-pton AF_INET6 "0:0:0:0:0:0:0:1")))
  63. (pass-if "::1"
  64. (eqv? 1 (inet-pton AF_INET6 "::1")))
  65. (pass-if "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
  66. (eqv? #xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  67. (inet-pton AF_INET6
  68. "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF")))
  69. (pass-if "F000:0000:0000:0000:0000:0000:0000:0000"
  70. (eqv? #xF0000000000000000000000000000000
  71. (inet-pton AF_INET6
  72. "F000:0000:0000:0000:0000:0000:0000:0000")))
  73. (pass-if "0F00:0000:0000:0000:0000:0000:0000:0000"
  74. (eqv? #x0F000000000000000000000000000000
  75. (inet-pton AF_INET6
  76. "0F00:0000:0000:0000:0000:0000:0000:0000")))
  77. (pass-if "0000:0000:0000:0000:0000:0000:0000:00F0"
  78. (eqv? #xF0
  79. (inet-pton AF_INET6
  80. "0000:0000:0000:0000:0000:0000:0000:00F0"))))))
  81. (if (defined? 'inet-ntop)
  82. (with-test-prefix "inet-ntop"
  83. (with-test-prefix "ipv4"
  84. (pass-if "127.0.0.1"
  85. (equal? "127.0.0.1" (inet-ntop AF_INET INADDR_LOOPBACK))))
  86. (if (defined? 'AF_INET6)
  87. (with-test-prefix "ipv6"
  88. (pass-if "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
  89. (string-ci=? "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
  90. (inet-ntop AF_INET6 (- (expt 2 128) 1))))
  91. (pass-if "::1"
  92. (equal? "::1" (inet-ntop AF_INET6 1)))))))
  93. ;;;
  94. ;;; make-socket-address
  95. ;;;
  96. (with-test-prefix "make-socket-address"
  97. (if (defined? 'AF_INET)
  98. (pass-if "AF_INET"
  99. (let ((sa (make-socket-address AF_INET 123456 80)))
  100. (and (= (sockaddr:fam sa) AF_INET)
  101. (= (sockaddr:addr sa) 123456)
  102. (= (sockaddr:port sa) 80)))))
  103. (if (defined? 'AF_INET6)
  104. (pass-if "AF_INET6"
  105. ;; Since the platform doesn't necessarily support `scopeid', we won't
  106. ;; test it.
  107. (let ((sa* (make-socket-address AF_INET6 123456 80 1))
  108. (sa+ (make-socket-address AF_INET6 123456 80)))
  109. (and (= (sockaddr:fam sa*) (sockaddr:fam sa+) AF_INET6)
  110. (= (sockaddr:addr sa*) (sockaddr:addr sa+) 123456)
  111. (= (sockaddr:port sa*) (sockaddr:port sa+) 80)
  112. (= (sockaddr:flowinfo sa*) 1)))))
  113. (if (defined? 'AF_UNIX)
  114. (pass-if "AF_UNIX"
  115. (let ((sa (make-socket-address AF_UNIX "/tmp/unix-socket")))
  116. (and (= (sockaddr:fam sa) AF_UNIX)
  117. (string=? (sockaddr:path sa) "/tmp/unix-socket"))))))
  118. ;;;
  119. ;;; ntohl
  120. ;;;
  121. (if (defined? 'ntohl)
  122. (with-test-prefix "ntohl"
  123. (pass-if "0" (eqv? 0 (ntohl 0)))
  124. (pass-if-exception "-1" exception:out-of-range
  125. (ntohl -1))
  126. ;; prior to guile 1.6.9 and 1.8.1, systems with 64-bit longs didn't detect
  127. ;; an overflow for values 2^32 <= x < 2^63
  128. (pass-if-exception "2^32" exception:out-of-range
  129. (ntohl (ash 1 32)))
  130. (pass-if-exception "2^1024" exception:out-of-range
  131. (ntohl (ash 1 1024)))))
  132. ;;;
  133. ;;; AF_UNIX sockets and `make-socket-address'
  134. ;;;
  135. (define %tmpdir
  136. ;; Honor `$TMPDIR', which tmpnam(3) doesn't do.
  137. (or (getenv "TMPDIR") "/tmp"))
  138. (define %curdir
  139. ;; Remember the current working directory.
  140. (getcwd))
  141. ;; Temporarily cd to %TMPDIR. The goal is to work around path name
  142. ;; limitations, which can lead to exceptions like:
  143. ;;
  144. ;; (misc-error "scm_to_sockaddr"
  145. ;; "unix address path too long: ~A"
  146. ;; ("/tmp/nix-build-fb7bph4ifh0vr3ihigm702dzffdnapfj-guile-coverage-1.9.5.drv-0/guile-test-socket-1258553296-77619")
  147. ;; #f)
  148. (chdir %tmpdir)
  149. (define (temp-file-path)
  150. ;; Return a temporary file name, assuming the current directory is %TMPDIR.
  151. (string-append "guile-test-socket-"
  152. (number->string (current-time)) "-"
  153. (number->string (random 100000))))
  154. (if (defined? 'AF_UNIX)
  155. (with-test-prefix "AF_UNIX/SOCK_DGRAM"
  156. ;; testing `bind' and `sendto' and datagram sockets
  157. (let ((server-socket (socket AF_UNIX SOCK_DGRAM 0))
  158. (server-bound? #f)
  159. (path (temp-file-path)))
  160. (pass-if "bind"
  161. (catch 'system-error
  162. (lambda ()
  163. (bind server-socket AF_UNIX path)
  164. (set! server-bound? #t)
  165. #t)
  166. (lambda args
  167. (let ((errno (system-error-errno args)))
  168. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  169. (else (apply throw args)))))))
  170. (pass-if "bind/sockaddr"
  171. (let* ((sock (socket AF_UNIX SOCK_STREAM 0))
  172. (path (temp-file-path))
  173. (sockaddr (make-socket-address AF_UNIX path)))
  174. (catch 'system-error
  175. (lambda ()
  176. (bind sock sockaddr)
  177. (false-if-exception (delete-file path))
  178. #t)
  179. (lambda args
  180. (let ((errno (system-error-errno args)))
  181. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  182. (else (apply throw args))))))))
  183. (pass-if "sendto"
  184. (if (not server-bound?)
  185. (throw 'unresolved)
  186. (let ((client (socket AF_UNIX SOCK_DGRAM 0))
  187. (message (string->utf8 "hello")))
  188. (> (sendto client message AF_UNIX path) 0))))
  189. (pass-if "sendto/sockaddr"
  190. (if (not server-bound?)
  191. (throw 'unresolved)
  192. (let ((client (socket AF_UNIX SOCK_DGRAM 0))
  193. (message (string->utf8 "hello"))
  194. (sockaddr (make-socket-address AF_UNIX path)))
  195. (> (sendto client message sockaddr) 0))))
  196. (false-if-exception (delete-file path)))))
  197. (if (defined? 'AF_UNIX)
  198. (with-test-prefix "AF_UNIX/SOCK_STREAM"
  199. ;; testing `bind', `listen' and `connect' on stream-oriented sockets
  200. (let ((server-socket (socket AF_UNIX SOCK_STREAM 0))
  201. (server-bound? #f)
  202. (server-listening? #f)
  203. (server-pid #f)
  204. (path (temp-file-path)))
  205. (pass-if "bind"
  206. (catch 'system-error
  207. (lambda ()
  208. (bind server-socket AF_UNIX path)
  209. (set! server-bound? #t)
  210. #t)
  211. (lambda args
  212. (let ((errno (system-error-errno args)))
  213. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  214. (else (apply throw args)))))))
  215. (pass-if "bind/sockaddr"
  216. (let* ((sock (socket AF_UNIX SOCK_STREAM 0))
  217. (path (temp-file-path))
  218. (sockaddr (make-socket-address AF_UNIX path)))
  219. (catch 'system-error
  220. (lambda ()
  221. (bind sock sockaddr)
  222. (false-if-exception (delete-file path))
  223. #t)
  224. (lambda args
  225. (let ((errno (system-error-errno args)))
  226. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  227. (else (apply throw args))))))))
  228. (pass-if "listen"
  229. (if (not server-bound?)
  230. (throw 'unresolved)
  231. (begin
  232. (listen server-socket 123)
  233. (set! server-listening? #t)
  234. #t)))
  235. (force-output (current-output-port))
  236. (force-output (current-error-port))
  237. (if server-listening?
  238. (let ((pid (primitive-fork)))
  239. ;; Spawn a server process.
  240. (case pid
  241. ((-1) (throw 'unresolved))
  242. ((0) ;; the kid: serve two connections and exit
  243. (let serve ((conn
  244. (false-if-exception (accept server-socket)))
  245. (count 1))
  246. (if (not conn)
  247. (exit 1)
  248. (if (> count 0)
  249. (serve (false-if-exception (accept server-socket))
  250. (- count 1)))))
  251. (exit 0))
  252. (else ;; the parent
  253. (set! server-pid pid)
  254. #t))))
  255. (pass-if "connect"
  256. (if (not server-pid)
  257. (throw 'unresolved)
  258. (let ((s (socket AF_UNIX SOCK_STREAM 0)))
  259. (connect s AF_UNIX path)
  260. #t)))
  261. (pass-if "connect/sockaddr"
  262. (if (not server-pid)
  263. (throw 'unresolved)
  264. (let ((s (socket AF_UNIX SOCK_STREAM 0)))
  265. (connect s (make-socket-address AF_UNIX path))
  266. #t)))
  267. (pass-if "accept"
  268. (if (not server-pid)
  269. (throw 'unresolved)
  270. (let ((status (cdr (waitpid server-pid))))
  271. (eq? 0 (status:exit-val status)))))
  272. (false-if-exception (delete-file path))
  273. #t)
  274. ;; Testing `send', `recv!' & co. on stream-oriented sockets (with
  275. ;; a bit of duplication with the above.)
  276. (let ((server-socket (socket AF_UNIX SOCK_STREAM 0))
  277. (server-bound? #f)
  278. (server-listening? #f)
  279. (server-pid #f)
  280. (message "hello, world!")
  281. (path (temp-file-path)))
  282. (define (sub-bytevector bv len)
  283. (let ((c (make-bytevector len)))
  284. (bytevector-copy! bv 0 c 0 len)
  285. c))
  286. (pass-if "bind (bis)"
  287. (catch 'system-error
  288. (lambda ()
  289. (bind server-socket AF_UNIX path)
  290. (set! server-bound? #t)
  291. #t)
  292. (lambda args
  293. (let ((errno (system-error-errno args)))
  294. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  295. (else (apply throw args)))))))
  296. (pass-if "listen (bis)"
  297. (if (not server-bound?)
  298. (throw 'unresolved)
  299. (begin
  300. (listen server-socket 123)
  301. (set! server-listening? #t)
  302. #t)))
  303. (force-output (current-output-port))
  304. (force-output (current-error-port))
  305. (if server-listening?
  306. (let ((pid (primitive-fork)))
  307. ;; Spawn a server process.
  308. (case pid
  309. ((-1) (throw 'unresolved))
  310. ((0) ;; the kid: send MESSAGE and exit
  311. (exit
  312. (false-if-exception
  313. (let ((conn (car (accept server-socket)))
  314. (bv (string->utf8 message)))
  315. (= (bytevector-length bv)
  316. (send conn bv))))))
  317. (else ;; the parent
  318. (set! server-pid pid)
  319. #t))))
  320. (pass-if "recv!"
  321. (if (not server-pid)
  322. (throw 'unresolved)
  323. (let ((s (socket AF_UNIX SOCK_STREAM 0)))
  324. (connect s AF_UNIX path)
  325. (let* ((buf (make-bytevector 123))
  326. (received (recv! s buf)))
  327. (string=? (utf8->string (sub-bytevector buf received))
  328. message)))))
  329. (pass-if "accept (bis)"
  330. (if (not server-pid)
  331. (throw 'unresolved)
  332. (let ((status (cdr (waitpid server-pid))))
  333. (eq? 0 (status:exit-val status)))))
  334. (false-if-exception (delete-file path))
  335. #t)))
  336. (if (defined? 'AF_INET6)
  337. (with-test-prefix "AF_INET6/SOCK_STREAM"
  338. ;; testing `bind', `listen' and `connect' on stream-oriented sockets
  339. (let ((server-socket
  340. ;; Some platforms don't support this protocol/family combination.
  341. (false-if-exception (socket AF_INET6 SOCK_STREAM 0)))
  342. (server-bound? #f)
  343. (server-listening? #f)
  344. (server-pid #f)
  345. (ipv6-addr 1) ; ::1
  346. (server-port 8889)
  347. (client-port 9998))
  348. (pass-if "bind"
  349. (if (not server-socket)
  350. (throw 'unresolved))
  351. (catch 'system-error
  352. (lambda ()
  353. (bind server-socket AF_INET6 ipv6-addr server-port)
  354. (set! server-bound? #t)
  355. #t)
  356. (lambda args
  357. (let ((errno (system-error-errno args)))
  358. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  359. (else (apply throw args)))))))
  360. (pass-if "bind/sockaddr"
  361. (let* ((sock (false-if-exception (socket AF_INET6 SOCK_STREAM 0)))
  362. (sockaddr (make-socket-address AF_INET6 ipv6-addr client-port)))
  363. (if (not sock)
  364. (throw 'unresolved))
  365. (catch 'system-error
  366. (lambda ()
  367. (bind sock sockaddr)
  368. #t)
  369. (lambda args
  370. (let ((errno (system-error-errno args)))
  371. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  372. (else (apply throw args))))))))
  373. (pass-if "listen"
  374. (if (not server-bound?)
  375. (throw 'unresolved)
  376. (begin
  377. (listen server-socket 123)
  378. (set! server-listening? #t)
  379. #t)))
  380. (force-output (current-output-port))
  381. (force-output (current-error-port))
  382. (if server-listening?
  383. (let ((pid (primitive-fork)))
  384. ;; Spawn a server process.
  385. (case pid
  386. ((-1) (throw 'unresolved))
  387. ((0) ;; the kid: serve two connections and exit
  388. (let serve ((conn
  389. (false-if-exception (accept server-socket)))
  390. (count 1))
  391. (if (not conn)
  392. (exit 1)
  393. (if (> count 0)
  394. (serve (false-if-exception (accept server-socket))
  395. (- count 1)))))
  396. (exit 0))
  397. (else ;; the parent
  398. (set! server-pid pid)
  399. #t))))
  400. (pass-if "connect"
  401. (if (not server-pid)
  402. (throw 'unresolved)
  403. (let ((s (socket AF_INET6 SOCK_STREAM 0)))
  404. (connect s AF_INET6 ipv6-addr server-port)
  405. #t)))
  406. (pass-if "connect/sockaddr"
  407. (if (not server-pid)
  408. (throw 'unresolved)
  409. (let ((s (socket AF_INET6 SOCK_STREAM 0)))
  410. (connect s (make-socket-address AF_INET6 ipv6-addr server-port))
  411. #t)))
  412. (pass-if "accept"
  413. (if (not server-pid)
  414. (throw 'unresolved)
  415. (let ((status (cdr (waitpid server-pid))))
  416. (eq? 0 (status:exit-val status)))))
  417. #t)))
  418. ;; Switch back to the previous directory.
  419. (false-if-exception (chdir %curdir))