socket.test 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. ;;;; socket.test --- test socket functions -*- scheme -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
  4. ;;;;
  5. ;;;; This library is free software; you can redistribute it and/or
  6. ;;;; modify it under the terms of the GNU Lesser General Public
  7. ;;;; License as published by the Free Software Foundation; either
  8. ;;;; version 2.1 of the License, or (at your option) any later version.
  9. ;;;;
  10. ;;;; This library is distributed in the hope that it will be useful,
  11. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. ;;;; Lesser General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU Lesser General Public
  16. ;;;; License along with this library; if not, write to the Free Software
  17. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. (define-module (test-suite test-socket)
  19. #:use-module (test-suite lib))
  20. ;;;
  21. ;;; htonl
  22. ;;;
  23. (if (defined? 'htonl)
  24. (with-test-prefix "htonl"
  25. (pass-if "0" (eqv? 0 (htonl 0)))
  26. (pass-if-exception "-1" exception:out-of-range
  27. (htonl -1))
  28. ;; prior to guile 1.6.9 and 1.8.1, systems with 64-bit longs didn't detect
  29. ;; an overflow for values 2^32 <= x < 2^63
  30. (pass-if-exception "2^32" exception:out-of-range
  31. (htonl (ash 1 32)))
  32. (pass-if-exception "2^1024" exception:out-of-range
  33. (htonl (ash 1 1024)))))
  34. ;;;
  35. ;;; inet-ntop
  36. ;;;
  37. (if (defined? 'inet-ntop)
  38. (with-test-prefix "inet-ntop"
  39. (with-test-prefix "ipv6"
  40. (pass-if "0"
  41. (string? (inet-ntop AF_INET6 0)))
  42. (pass-if "2^128-1"
  43. (string? (inet-ntop AF_INET6 (1- (ash 1 128)))))
  44. (pass-if-exception "-1" exception:out-of-range
  45. (inet-ntop AF_INET6 -1))
  46. (pass-if-exception "2^128" exception:out-of-range
  47. (inet-ntop AF_INET6 (ash 1 128)))
  48. (pass-if-exception "2^1024" exception:out-of-range
  49. (inet-ntop AF_INET6 (ash 1 1024))))))
  50. ;;;
  51. ;;; inet-pton
  52. ;;;
  53. (if (defined? 'inet-pton)
  54. (with-test-prefix "inet-pton"
  55. (with-test-prefix "ipv6"
  56. (pass-if "00:00:00:00:00:00:00:00"
  57. (eqv? 0 (inet-pton AF_INET6 "00:00:00:00:00:00:00:00")))
  58. (pass-if "0:0:0:0:0:0:0:1"
  59. (eqv? 1 (inet-pton AF_INET6 "0:0:0:0:0:0:0:1")))
  60. (pass-if "::1"
  61. (eqv? 1 (inet-pton AF_INET6 "::1")))
  62. (pass-if "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
  63. (eqv? #xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  64. (inet-pton AF_INET6
  65. "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF")))
  66. (pass-if "F000:0000:0000:0000:0000:0000:0000:0000"
  67. (eqv? #xF0000000000000000000000000000000
  68. (inet-pton AF_INET6
  69. "F000:0000:0000:0000:0000:0000:0000:0000")))
  70. (pass-if "0F00:0000:0000:0000:0000:0000:0000:0000"
  71. (eqv? #x0F000000000000000000000000000000
  72. (inet-pton AF_INET6
  73. "0F00:0000:0000:0000:0000:0000:0000:0000")))
  74. (pass-if "0000:0000:0000:0000:0000:0000:0000:00F0"
  75. (eqv? #xF0
  76. (inet-pton AF_INET6
  77. "0000:0000:0000:0000:0000:0000:0000:00F0"))))))
  78. (if (defined? 'inet-ntop)
  79. (with-test-prefix "inet-ntop"
  80. (with-test-prefix "ipv4"
  81. (pass-if "127.0.0.1"
  82. (equal? "127.0.0.1" (inet-ntop AF_INET INADDR_LOOPBACK))))
  83. (if (defined? 'AF_INET6)
  84. (with-test-prefix "ipv6"
  85. (pass-if "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
  86. (string-ci=? "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
  87. (inet-ntop AF_INET6 (- (expt 2 128) 1))))
  88. (pass-if "::1"
  89. (equal? "::1" (inet-ntop AF_INET6 1)))))))
  90. ;;;
  91. ;;; make-socket-address
  92. ;;;
  93. (with-test-prefix "make-socket-address"
  94. (if (defined? 'AF_INET)
  95. (pass-if "AF_INET"
  96. (let ((sa (make-socket-address AF_INET 123456 80)))
  97. (and (= (sockaddr:fam sa) AF_INET)
  98. (= (sockaddr:addr sa) 123456)
  99. (= (sockaddr:port sa) 80)))))
  100. (if (defined? 'AF_INET6)
  101. (pass-if "AF_INET6"
  102. ;; Since the platform doesn't necessarily support `scopeid', we won't
  103. ;; test it.
  104. (let ((sa* (make-socket-address AF_INET6 123456 80 1))
  105. (sa+ (make-socket-address AF_INET6 123456 80)))
  106. (and (= (sockaddr:fam sa*) (sockaddr:fam sa+) AF_INET6)
  107. (= (sockaddr:addr sa*) (sockaddr:addr sa+) 123456)
  108. (= (sockaddr:port sa*) (sockaddr:port sa+) 80)
  109. (= (sockaddr:flowinfo sa*) 1)))))
  110. (if (defined? 'AF_UNIX)
  111. (pass-if "AF_UNIX"
  112. (let ((sa (make-socket-address AF_UNIX "/tmp/unix-socket")))
  113. (and (= (sockaddr:fam sa) AF_UNIX)
  114. (string=? (sockaddr:path sa) "/tmp/unix-socket"))))))
  115. ;;;
  116. ;;; ntohl
  117. ;;;
  118. (if (defined? 'ntohl)
  119. (with-test-prefix "ntohl"
  120. (pass-if "0" (eqv? 0 (ntohl 0)))
  121. (pass-if-exception "-1" exception:out-of-range
  122. (ntohl -1))
  123. ;; prior to guile 1.6.9 and 1.8.1, systems with 64-bit longs didn't detect
  124. ;; an overflow for values 2^32 <= x < 2^63
  125. (pass-if-exception "2^32" exception:out-of-range
  126. (ntohl (ash 1 32)))
  127. (pass-if-exception "2^1024" exception:out-of-range
  128. (ntohl (ash 1 1024)))))
  129. ;;;
  130. ;;; AF_UNIX sockets and `make-socket-address'
  131. ;;;
  132. (define (temp-file-path)
  133. ;; Return a temporary file path that honors `$TMPDIR', which `tmpnam'
  134. ;; doesn't do.
  135. (let ((dir (or (getenv "TMPDIR") "/tmp")))
  136. (string-append dir "/guile-test-socket-"
  137. (number->string (current-time)) "-"
  138. (number->string (random 100000)))))
  139. (if (defined? 'AF_UNIX)
  140. (with-test-prefix "AF_UNIX/SOCK_DGRAM"
  141. ;; testing `bind' and `sendto' and datagram sockets
  142. (let ((server-socket (socket AF_UNIX SOCK_DGRAM 0))
  143. (server-bound? #f)
  144. (path (temp-file-path)))
  145. (pass-if "bind"
  146. (catch 'system-error
  147. (lambda ()
  148. (bind server-socket AF_UNIX path)
  149. (set! server-bound? #t)
  150. #t)
  151. (lambda args
  152. (let ((errno (system-error-errno args)))
  153. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  154. (else (apply throw args)))))))
  155. (pass-if "bind/sockaddr"
  156. (let* ((sock (socket AF_UNIX SOCK_STREAM 0))
  157. (path (temp-file-path))
  158. (sockaddr (make-socket-address AF_UNIX path)))
  159. (catch 'system-error
  160. (lambda ()
  161. (bind sock sockaddr)
  162. (false-if-exception (delete-file path))
  163. #t)
  164. (lambda args
  165. (let ((errno (system-error-errno args)))
  166. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  167. (else (apply throw args))))))))
  168. (pass-if "sendto"
  169. (if (not server-bound?)
  170. (throw 'unresolved)
  171. (let ((client (socket AF_UNIX SOCK_DGRAM 0)))
  172. (> (sendto client "hello" AF_UNIX path) 0))))
  173. (pass-if "sendto/sockaddr"
  174. (if (not server-bound?)
  175. (throw 'unresolved)
  176. (let ((client (socket AF_UNIX SOCK_DGRAM 0))
  177. (sockaddr (make-socket-address AF_UNIX path)))
  178. (> (sendto client "hello" sockaddr) 0))))
  179. (false-if-exception (delete-file path)))))
  180. (if (defined? 'AF_UNIX)
  181. (with-test-prefix "AF_UNIX/SOCK_STREAM"
  182. ;; testing `bind', `listen' and `connect' on stream-oriented sockets
  183. (let ((server-socket (socket AF_UNIX SOCK_STREAM 0))
  184. (server-bound? #f)
  185. (server-listening? #f)
  186. (server-pid #f)
  187. (path (temp-file-path)))
  188. (pass-if "bind"
  189. (catch 'system-error
  190. (lambda ()
  191. (bind server-socket AF_UNIX path)
  192. (set! server-bound? #t)
  193. #t)
  194. (lambda args
  195. (let ((errno (system-error-errno args)))
  196. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  197. (else (apply throw args)))))))
  198. (pass-if "bind/sockaddr"
  199. (let* ((sock (socket AF_UNIX SOCK_STREAM 0))
  200. (path (temp-file-path))
  201. (sockaddr (make-socket-address AF_UNIX path)))
  202. (catch 'system-error
  203. (lambda ()
  204. (bind sock sockaddr)
  205. (false-if-exception (delete-file path))
  206. #t)
  207. (lambda args
  208. (let ((errno (system-error-errno args)))
  209. (cond ((= errno EADDRINUSE) (throw 'unresolved))
  210. (else (apply throw args))))))))
  211. (pass-if "listen"
  212. (if (not server-bound?)
  213. (throw 'unresolved)
  214. (begin
  215. (listen server-socket 123)
  216. (set! server-listening? #t)
  217. #t)))
  218. (if server-listening?
  219. (let ((pid (primitive-fork)))
  220. ;; Spawn a server process.
  221. (case pid
  222. ((-1) (throw 'unresolved))
  223. ((0) ;; the kid: serve two connections and exit
  224. (let serve ((conn
  225. (false-if-exception (accept server-socket)))
  226. (count 1))
  227. (if (not conn)
  228. (exit 1)
  229. (if (> count 0)
  230. (serve (false-if-exception (accept server-socket))
  231. (- count 1)))))
  232. (exit 0))
  233. (else ;; the parent
  234. (set! server-pid pid)
  235. #t))))
  236. (pass-if "connect"
  237. (if (not server-pid)
  238. (throw 'unresolved)
  239. (let ((s (socket AF_UNIX SOCK_STREAM 0)))
  240. (connect s AF_UNIX path)
  241. #t)))
  242. (pass-if "connect/sockaddr"
  243. (if (not server-pid)
  244. (throw 'unresolved)
  245. (let ((s (socket AF_UNIX SOCK_STREAM 0)))
  246. (connect s (make-socket-address AF_UNIX path))
  247. #t)))
  248. (pass-if "accept"
  249. (if (not server-pid)
  250. (throw 'unresolved)
  251. (let ((status (cdr (waitpid server-pid))))
  252. (eq? 0 (status:exit-val status)))))
  253. (false-if-exception (delete-file path))
  254. #t)))