Misc improvements to net/dns' and net/private/ip'.

* Some racketisms.

* Use explicit `in-list' etc in for loops.

* Remove some redundant requires from `net/dns'.

* Move all tests to `tests/net', including a new `tests/net/ip'.  In the
  future there's a plan to have things like stripped zos etc for
  distribution, but we're not there yet, and the net collection is
  already organized nicely so this also makes it more uniform.

* Include the dns tests in the main test file.

original commit: 6149134011
This commit is contained in:
Eli Barzilay 2013-04-05 01:29:05 -04:00
parent 518051a4b3
commit 92358cb553
6 changed files with 306 additions and 325 deletions

View File

@ -3,15 +3,11 @@
;; DNS query library for Racket
(require "private/ip.rkt"
racket/bool
racket/contract
racket/format
racket/list
racket/match
racket/string
racket/system
racket/udp
(only-in unstable/sequence in-slice))
racket/udp)
(provide (contract-out
[dns-get-address
@ -29,8 +25,6 @@
[dns-find-nameserver
(-> (or/c ip-address-string? #f))]))
(module+ test (require rackunit))
;; UDP retry timeout:
(define INIT-TIMEOUT 50)
@ -88,13 +82,13 @@
;; Convert the domain name into a sequence of labels, where each
;; label is a length octet and then that many octets
(define (name->octets s)
(let ([do-one (lambda (s) (cons (bytes-length s) (bytes->list s)))])
(define (do-one s) (cons (bytes-length s) (bytes->list s)))
(let loop ([s s])
(let ([m (regexp-match #rx#"^([^.]*)[.](.*)" s)])
(define m (regexp-match #rx#"^([^.]*)[.](.*)" s))
(if m
(append (do-one (cadr m)) (loop (caddr m)))
;; terminate with zero length octet
(append (do-one s) (list 0)))))))
(append (do-one s) (list 0)))))
;; The query header. See RFC1035 4.1.1 for details
;;
@ -134,7 +128,7 @@
(car rr))
(define (parse-name start reply)
(let ([v (car start)])
(define v (car start))
(cond
[(zero? v)
;; End of name
@ -144,17 +138,16 @@
(let loop ([len v] [start (cdr start)] [accum null])
(if (zero? len)
(let-values ([(s start) (parse-name start reply)])
(let ([s0 (list->bytes (reverse accum))])
(define s0 (list->bytes (reverse accum)))
(values (if s (bytes-append s0 #"." s) s0)
start)))
start))
(loop (sub1 len) (cdr start) (cons (car start) accum))))]
[else
;; Compression offset
(let ([offset (+ (arithmetic-shift (bitwise-and #x3f v) 8)
(cadr start))])
(let-values ([(s ignore-start)
(parse-name (list-tail reply offset) reply)])
(values s (cddr start))))])))
(define offset (+ (arithmetic-shift (bitwise-and #x3f v) 8)
(cadr start)))
(define-values [s ignore-start] (parse-name (list-tail reply offset) reply))
(values s (cddr start))]))
(define (parse-rr start reply)
(let-values ([(name start) (parse-name start reply)])
@ -205,33 +198,28 @@
(raise-type-error 'dns-query "DNS query class" class))
(define nameserver (ip-address->string nameserver-ip))
(let* ([query (make-query (random 256) (string->bytes/latin-1 addr)
type class)]
[udp (udp-open-socket nameserver 53)]
[reply
(define query (make-query (random 256) (string->bytes/latin-1 addr)
type class))
(define udp (udp-open-socket nameserver 53))
(define reply
(dynamic-wind
void
(lambda ()
(let ([s (make-bytes 512)])
(define s (make-bytes 512))
(let retry ([timeout INIT-TIMEOUT])
(udp-send-to udp nameserver 53 (list->bytes query))
(sync (handle-evt (udp-receive!-evt udp s)
(lambda (r)
(bytes->list (subbytes s 0 (car r)))))
(lambda (r) (bytes->list (subbytes s 0 (car r)))))
(handle-evt (alarm-evt (+ (current-inexact-milliseconds)
timeout))
(lambda (v)
(retry (* timeout 2))))))))
(lambda () (udp-close udp)))])
(lambda (v) (retry (* timeout 2)))))))
(lambda () (udp-close udp))))
;; First two bytes must match sent message id:
(unless (and (= (car reply) (car query))
(= (cadr reply) (cadr query)))
(error 'dns-query "bad reply id from server"))
(let ([v0 (caddr reply)]
[v1 (cadddr reply)])
(define v0 (caddr reply))
(define v1 (cadddr reply))
;; Check for error code:
(let ([rcode (bitwise-and #xf v1)])
(unless (zero? rcode)
@ -242,13 +230,11 @@
[(3) "name error"]
[(4) "not implemented"]
[(5) "refused"]))))
(let ([qd-count (octet-pair->number (list-ref reply 4) (list-ref reply 5))]
[an-count (octet-pair->number (list-ref reply 6) (list-ref reply 7))]
[ns-count (octet-pair->number (list-ref reply 8) (list-ref reply 9))]
[ar-count (octet-pair->number (list-ref reply 10) (list-ref reply 11))])
(let ([start (list-tail reply 12)])
(define qd-count (octet-pair->number (list-ref reply 4) (list-ref reply 5)))
(define an-count (octet-pair->number (list-ref reply 6) (list-ref reply 7)))
(define ns-count (octet-pair->number (list-ref reply 8) (list-ref reply 9)))
(define ar-count (octet-pair->number (list-ref reply 10) (list-ref reply 11)))
(define start (list-tail reply 12))
(let*-values ([(qds start) (parse-n parse-ques start reply qd-count)]
[(ans start) (parse-n parse-rr start reply an-count)]
[(nss start) (parse-n parse-rr start reply ns-count)]
@ -256,7 +242,7 @@
(unless (null? start)
(error 'dns-query "error parsing server reply"))
(values (positive? (bitwise-and #x4 v0))
qds ans nss ars reply)))))))
qds ans nss ars reply)))
;; A cache for DNS query data
;; Stores a (List Boolean LB LB LB LB LB)
@ -290,7 +276,7 @@
(let-values ([(v ars auth?) (k nameserver)])
(or v
(and (not auth?)
(let* ([ns (ormap (lambda (ar)
(let ([ns (ormap (lambda (ar)
(and (eq? (rr-type ar) 'a)
(ip->string (rr-data ar))))
ars)])
@ -307,41 +293,21 @@
;; Convert an IPv4 address for reverse lookup
(define (ip->in-addr.arpa ip)
(define bytes (ipv4-bytes ip))
(format "~a.~a.~a.~a.in-addr.arpa"
(bytes-ref bytes 3) (bytes-ref bytes 2)
(bytes-ref bytes 1) (bytes-ref bytes 0)))
(module+ test
(check-equal? (ip->in-addr.arpa (ipv4 (bytes 8 8 8 8)))
"8.8.8.8.in-addr.arpa")
(check-equal? (ip->in-addr.arpa (ipv4 (bytes 127 0 0 1)))
"1.0.0.127.in-addr.arpa"))
(apply format "~a.~a.~a.~a.in-addr.arpa"
(reverse (bytes->list (ipv4-bytes ip)))))
;; Convert an IPv6 address for reverse lookup
(define (ip->ip6.arpa ip)
(define nibbles
(string-join
(for/fold ([nibbles '()])
([byte (ipv6-bytes ip)])
([byte (in-bytes (ipv6-bytes ip))])
(define nib1 (arithmetic-shift (bitwise-and #xf0 byte) -4))
(define nib2 (bitwise-and #x0f byte))
(append (list nib2 nib1) nibbles)))
(string-append
(string-join
(for/list ([n nibbles]) (~r n #:base 16))
".")
".ip6.arpa"))
(module+ test
(check-equal?
(ip->ip6.arpa (make-ip-address "4321:0:1:2:3:4:567:89ab"))
"b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa")
(check-equal?
(ip->ip6.arpa (make-ip-address "2001:db8::567:89ab"))
"b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa"))
(append (list (~r nib2 #:base 16) (~r nib1 #:base 16)) nibbles))
"." #:after-last ".ip6.arpa"))
(define (get-ptr-list-from-ans ans)
(filter (lambda (ans-entry) (eq? (list-ref ans-entry 1) 'ptr)) ans))
(filter (λ (ans-entry) (eq? (list-ref ans-entry 1) 'ptr)) ans))
(define (dns-get-name nameserver-ip-or-string ip-or-string)
(define nameserver (if (ip-address? nameserver-ip-or-string)
@ -365,7 +331,7 @@
;; Get resource records corresponding to the given type
(define (get-records-from-ans ans type)
(for/list ([ans-entry ans]
(for/list ([ans-entry (in-list ans)]
#:when (eq? (list-ref ans-entry 1) type))
ans-entry))
@ -404,12 +370,12 @@
nss)
addr))]
[else
(let ([d (rr-data (car ans))])
(let ([pref (octet-pair->number (car d) (cadr d))])
(define d (rr-data (car ans)))
(define pref (octet-pair->number (car d) (cadr d)))
(if (< pref best-pref)
(let-values ([(name start) (parse-name (cddr d) reply)])
(loop (cdr ans) pref name))
(loop (cdr ans) best-pref exchanger))))]))
(loop (cdr ans) best-pref exchanger))]))
ars auth?)))
nameserver)
(error 'dns-get-mail-exchanger "bad address")))
@ -421,16 +387,16 @@
(with-input-from-file "/etc/resolv.conf"
(lambda ()
(let loop ()
(let ([l (read-line)])
(or (and (string? l)
(define line (read-line))
(or (and (string? line)
(let ([m (regexp-match
#rx"nameserver[ \t]+([0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)"
l)])
line)])
(and m (cadr m))))
(and (not (eof-object? l))
(loop))))))))]
(and (not (eof-object? line))
(loop)))))))]
[(windows)
(let ([nslookup (find-executable-path "nslookup.exe" #f)])
(define nslookup (find-executable-path "nslookup.exe" #f))
(and nslookup
(let-values ([(pin pout pid perr proc)
(apply
@ -439,7 +405,7 @@
#f (open-input-file "NUL") (current-error-port)
nslookup))])
(let loop ([name #f] [ip #f] [try-ip? #f])
(let ([line (read-line pin 'any)])
(define line (read-line pin 'any))
(cond [(eof-object? line)
(close-input-port pin)
(proc 'wait)
@ -450,5 +416,5 @@
[(and try-ip?
(regexp-match #rx"^Address: +(.*)$" line))
=> (lambda (m) (loop name (cadr m) #f))]
[else (loop name ip #f)]))))))]
[else (loop name ip #f)]))))]
[else #f]))

View File

@ -34,8 +34,6 @@
(struct ipv4 ([bytes (bytes-of-length 4)]))
(struct ipv6 ([bytes (bytes-of-length 16)]))))
(module+ test (require rackunit))
;; data definitions
;; An IPAddress is one of
@ -73,26 +71,6 @@
[(? (bytes-of-length 4)) (ipv4 input)]
[(? (bytes-of-length 16)) (ipv6 input)]))
(module+ test
(check-equal? (make-ip-address "127.0.0.1")
(ipv4 (bytes 127 0 0 1)))
(check-equal? (make-ip-address (bytes 127 0 0 1))
(ipv4 (bytes 127 0 0 1)))
(check-equal? (make-ip-address "2607:f8b0:4009:800::100e")
(ipv6 (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14)))
(check-equal? (make-ip-address (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14))
(ipv6 (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14)))
(check-equal? (make-ip-address "0.0.0.1")
(ipv4 (bytes 0 0 0 1)))
(check-not-equal? (make-ip-address "128.0.0.1")
(make-ip-address "255.3.255.0"))
(let ([ip-bytes (bytes 127 0 0 1)])
(define ip (make-ip-address ip-bytes))
(bytes-set! ip-bytes 0 255)
(check-equal? ip (make-ip-address "127.0.0.1")
"IP addresses should be immutable")))
(define (ip-address-string? val)
(and (string? val)
(or (ipv4-string? val)
@ -147,39 +125,6 @@
;; this is the +1 octet pair
(regexp-match? re-end str))]))))
(module+ test
(check-true (ip-address-string? "0.0.0.0"))
(check-true (ip-address-string? "0.1.0.2"))
(check-true (ip-address-string? "8.8.8.8"))
(check-true (ip-address-string? "12.81.255.109"))
(check-true (ip-address-string? "192.168.0.1"))
(check-true (ip-address-string? "2001:0db8:85a3:0000:0000:8a2e:0370:7334"))
(check-true (ip-address-string? "2001:200:dff:fff1:216:3eff:feb1:44d7"))
(check-true (ip-address-string? "2001:db8:85a3:0:0:8a2e:370:7334"))
(check-true (ip-address-string? "2001:db8:85a3::8a2e:370:7334"))
(check-true (ip-address-string? "0:0:0:0:0:0:0:1"))
(check-true (ip-address-string? "0:0:0:0:0:0:0:0"))
(check-true (ip-address-string? "::"))
(check-true (ip-address-string? "::0"))
(check-true (ip-address-string? "::ffff:c000:0280"))
(check-true (ip-address-string? "2001:db8::2:1"))
(check-true (ip-address-string? "2001:db8:0:0:1::1"))
(check-false (ip-address-string? ""))
(check-false (ip-address-string? ":::"))
(check-false (ip-address-string? "::0::"))
(check-false (ip-address-string? "2001::db8::2:1"))
(check-false (ip-address-string? "2001:::db8:2:1"))
(check-false (ip-address-string? "52001:db8::2:1"))
(check-false (ip-address-string? "80.8.800.8"))
(check-false (ip-address-string? "80.8.800.0"))
(check-false (ip-address-string? "080.8.800.8"))
(check-false (ip-address-string? "vas8.8.800.8"))
(check-false (ip-address-string? "80.8.128.8dd"))
(check-false (ip-address-string? "0.8.800.008"))
(check-false (ip-address-string? "0.8.800.a8"))
(check-false (ip-address-string? "potatoes"))
(check-false (ip-address-string? "127.0.0")))
;; String -> Bytes
;; converts a string representating an IPv4 address to bytes
(define (ipv4-string->bytes ip)
@ -190,16 +135,6 @@
(string->number (list-ref result 3))
(string->number (list-ref result 4)))))
(module+ test
(check-equal? (ipv4-string->bytes "0.8.255.0")
(bytes 0 8 255 0))
(check-equal? (ipv4-string->bytes "8.8.8.8")
(bytes 8 8 8 8))
(check-equal? (ipv4-string->bytes "12.81.255.109")
(bytes 12 81 255 109))
(check-equal? (ipv4-string->bytes "192.168.0.1")
(bytes 192 168 0 1)))
;; String -> Bytes
;; converts a string representing an IPv6 address to bytes
(define (ipv6-string->bytes ip)
@ -224,22 +159,6 @@
(loop (bytes-append result (octet-pair-string->bytes (car splitted)))
(cdr splitted))])))
(module+ test
(check-equal? (ipv6-string->bytes "2001:0db8:85a3:0000:0000:8a2e:0370:7334")
(bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52))
(check-equal? (ipv6-string->bytes "2001:200:dff:fff1:216:3eff:feb1:44d7")
(bytes 32 1 2 0 13 255 255 241 2 22 62 255 254 177 68 215))
(check-equal? (ipv6-string->bytes "2001:db8:85a3:0:0:8a2e:370:7334")
(bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52))
(check-equal? (ipv6-string->bytes "2001:db8:85a3::8a2e:370:7334")
(bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52))
(check-equal? (ipv6-string->bytes "2607:f8b0:4009:800::100e")
(bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14))
(check-equal? (ipv6-string->bytes "::1")
(bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1))
(check-equal? (ipv6-string->bytes "::ffff")
(bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255)))
;; IPAddress -> Bytestring
;; Turn an ip struct into a byte string
(define (ip-address->bytes ip)
@ -247,12 +166,6 @@
[(? ipv4?) (ipv4-bytes ip)]
[(? ipv6?) (ipv6-bytes ip)]))
(module+ test
(check-equal? (ip-address->bytes (make-ip-address "8.8.8.8"))
(bytes 8 8 8 8))
(check-equal? (ip-address->bytes (make-ip-address "::1"))
(bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)))
;; IPAddress -> String
;; Convert an IP address to a string
(define (ip-address->string ip)
@ -260,25 +173,10 @@
[(? ipv4?) (ipv4->string (ipv4-bytes ip))]
[(? ipv6?) (ipv6->string (ipv6-bytes ip))]))
(module+ test
(check-equal? (ip-address->string (make-ip-address "8.8.8.8"))
"8.8.8.8")
(check-equal? (ip-address->string (make-ip-address "::1"))
"::1"))
;; Bytes -> String
;; Convert a bytestring for an IPv4 address to a string
(define (ipv4->string bytes)
(string-join (for/list ([b bytes]) (~r b)) "."))
(module+ test
(check-equal? (ipv4->string (bytes 0 0 0 0)) "0.0.0.0")
(check-equal? (ipv4->string (bytes 255 255 0 1))
"255.255.0.1")
(check-equal? (ipv4->string (bytes 127 0 0 1))
"127.0.0.1")
(check-equal? (ipv4->string (bytes 8 8 8 8))
"8.8.8.8"))
(string-join (for/list ([b (in-bytes bytes)]) (~r b)) "."))
;; Bytes -> String
;; Convert a bytestring representing an IPv6 address to a string
@ -291,7 +189,7 @@
(define compressed (compress two-octets))
;; add an extra "" if :: is at the start
(define compressed-strs
(for/list ([elem compressed])
(for/list ([elem (in-list compressed)])
(if (eq? elem '::)
"" ; string-join will turn this into ::
(~r elem #:base 16))))
@ -301,41 +199,21 @@
compressed-strs))
(string-join compressed-strs* ":"))
(module+ test
(check-equal? (ipv6->string (bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52))
"2001:db8:85a3::8a2e:370:7334")
(check-equal? (ipv6->string (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14))
"2607:f8b0:4009:800::100e")
(check-equal? (ipv6->string (bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255))
"::ffff")
(check-equal? (ipv6->string (bytes 255 255 0 0 0 0 0 0 0 0 0 0 0 0 255 255))
"ffff::ffff"))
;; (Listof Number) -> (Listof (U Number '::))
;; Compress an IPv6 address to its shortest representation
(define (compress lon)
(let loop ([acc '()] [lon lon])
(cond [(empty? lon) (reverse acc)]
[else
(define zeroes (for/list ([n lon] #:break (not (zero? n))) n))
(define zeroes
(for/list ([n (in-list lon)] #:break (not (zero? n))) n))
(define num-zs (length zeroes))
(if (<= num-zs 1)
(loop (cons (car lon) acc) (cdr lon))
(append (reverse acc) '(::) (drop lon num-zs)))])))
(module+ test
(check-equal? (compress '(0 0 0 5 5)) '(:: 5 5))
(check-equal? (compress '(0 5 5)) '(0 5 5))
(check-equal? (compress '(0 0 5 0 0 5)) '(:: 5 0 0 5))
(check-equal? (compress '(0 5 0 0 0 5)) '(0 5 :: 5)))
;; contract helper
(define (bytes-of-length n)
(flat-named-contract
`(bytes-of-length ,n)
(λ (bs) (and (bytes? bs) (= (bytes-length bs) n)))))
(module+ test
(check-true ((bytes-of-length 5) (bytes 1 2 3 4 5)))
(check-false ((bytes-of-length 5) "moogle")))

View File

@ -2,8 +2,20 @@
(require net/dns tests/eli-tester)
;; Run internal unit tests
(require (submod net/dns test))
;; internal tests
(require (only-in rackunit require/expose) net/private/ip)
(require/expose net/dns (ip->in-addr.arpa ip->ip6.arpa))
(define (internal-tests)
(test (ip->in-addr.arpa (ipv4 (bytes 8 8 8 8)))
=> "8.8.8.8.in-addr.arpa"
(ip->in-addr.arpa (ipv4 (bytes 127 0 0 1)))
=> "1.0.0.127.in-addr.arpa"
(ip->ip6.arpa (make-ip-address "4321:0:1:2:3:4:567:89ab"))
=> (string-append "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0"
".2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.arpa")
(ip->ip6.arpa (make-ip-address "2001:db8::567:89ab"))
=> (string-append "b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0"
".0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa")))
;; Constants for testing. These can go out of sync
;; when server setups change, so keep them up-to-date.
@ -16,19 +28,17 @@
(define *kame-url* "www.kame.net")
(define *kame-ip* "2001:200:dff:fff1:216:3eff:feb1:44d7")
(module+ main (tests))
(define (dns-test/nameserver nameserver)
(define (nameserver-tests nameserver)
(test (dns-get-address nameserver *racket-url*) => *racket-ip*
(dns-get-address nameserver *racket-host*) => *racket-ip*
(dns-get-address nameserver *kame-url* #:ipv6? #t) => *kame-ip*
(dns-get-name nameserver *racket-ip*) => *racket-host*
(dns-get-mail-exchanger nameserver *racket-url*) => *racket-mx*))
(provide tests)
(module+ main (tests))
(define (tests)
(dns-test/nameserver *google-dns*)
(dns-test/nameserver *google-dns-2*)
(define ns (dns-find-nameserver))
(when ns
(dns-test/nameserver ns)))
(test do (internal-tests)
(nameserver-tests *google-dns*)
(nameserver-tests *google-dns-2*)
(let ([ns (dns-find-nameserver)]) (when ns (nameserver-tests ns)))))

125
collects/tests/net/ip.rkt Normal file
View File

@ -0,0 +1,125 @@
#lang racket/base
(require net/private/ip tests/eli-tester)
(require (only-in rackunit require/expose))
(require/expose net/private/ip
(ipv4-string->bytes ipv6-string->bytes ipv4->string ipv6->string
compress bytes-of-length))
(provide tests)
(module+ main (tests))
(define (tests)
(test
;; ----------------------------------------
(make-ip-address "127.0.0.1")
=> (ipv4 (bytes 127 0 0 1))
(make-ip-address (bytes 127 0 0 1))
=> (ipv4 (bytes 127 0 0 1))
(make-ip-address "2607:f8b0:4009:800::100e")
=> (ipv6 (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14))
(make-ip-address (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14))
=> (ipv6 (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14))
(make-ip-address "0.0.0.1")
=> (ipv4 (bytes 0 0 0 1))
(not (equal? (make-ip-address "128.0.0.1")
(make-ip-address "255.3.255.0")))
do (let ([ip-bytes (bytes 127 0 0 1)])
(define ip (make-ip-address ip-bytes))
(bytes-set! ip-bytes 0 255)
(test #:failure-message "IP addresses should be immutable"
ip => (make-ip-address "127.0.0.1")))
;; ----------------------------------------
(ip-address-string? "0.0.0.0")
(ip-address-string? "0.1.0.2")
(ip-address-string? "8.8.8.8")
(ip-address-string? "12.81.255.109")
(ip-address-string? "192.168.0.1")
(ip-address-string? "2001:0db8:85a3:0000:0000:8a2e:0370:7334")
(ip-address-string? "2001:200:dff:fff1:216:3eff:feb1:44d7")
(ip-address-string? "2001:db8:85a3:0:0:8a2e:370:7334")
(ip-address-string? "2001:db8:85a3::8a2e:370:7334")
(ip-address-string? "0:0:0:0:0:0:0:1")
(ip-address-string? "0:0:0:0:0:0:0:0")
(ip-address-string? "::")
(ip-address-string? "::0")
(ip-address-string? "::ffff:c000:0280")
(ip-address-string? "2001:db8::2:1")
(ip-address-string? "2001:db8:0:0:1::1")
(not (ip-address-string? ""))
(not (ip-address-string? ":::"))
(not (ip-address-string? "::0::"))
(not (ip-address-string? "2001::db8::2:1"))
(not (ip-address-string? "2001:::db8:2:1"))
(not (ip-address-string? "52001:db8::2:1"))
(not (ip-address-string? "80.8.800.8"))
(not (ip-address-string? "80.8.800.0"))
(not (ip-address-string? "080.8.800.8"))
(not (ip-address-string? "vas8.8.800.8"))
(not (ip-address-string? "80.8.128.8dd"))
(not (ip-address-string? "0.8.800.008"))
(not (ip-address-string? "0.8.800.a8"))
(not (ip-address-string? "potatoes"))
(not (ip-address-string? "127.0.0"))
;; ----------------------------------------
(ipv4-string->bytes "0.8.255.0")
=> (bytes 0 8 255 0)
(ipv4-string->bytes "8.8.8.8")
=> (bytes 8 8 8 8)
(ipv4-string->bytes "12.81.255.109")
=> (bytes 12 81 255 109)
(ipv4-string->bytes "192.168.0.1")
=> (bytes 192 168 0 1)
;; ----------------------------------------
(ipv6-string->bytes "2001:0db8:85a3:0000:0000:8a2e:0370:7334")
=> (bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52)
(ipv6-string->bytes "2001:200:dff:fff1:216:3eff:feb1:44d7")
=> (bytes 32 1 2 0 13 255 255 241 2 22 62 255 254 177 68 215)
(ipv6-string->bytes "2001:db8:85a3:0:0:8a2e:370:7334")
=> (bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52)
(ipv6-string->bytes "2001:db8:85a3::8a2e:370:7334")
=> (bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52)
(ipv6-string->bytes "2607:f8b0:4009:800::100e")
=> (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14)
(ipv6-string->bytes "::1")
=> (bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)
(ipv6-string->bytes "::ffff")
=> (bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255)
;; ----------------------------------------
(ip-address->bytes (make-ip-address "8.8.8.8"))
=> (bytes 8 8 8 8)
(ip-address->bytes (make-ip-address "::1"))
=> (bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)
;; ----------------------------------------
(ip-address->string (make-ip-address "8.8.8.8"))
=> "8.8.8.8"
(ip-address->string (make-ip-address "::1"))
=> "::1"
;; ----------------------------------------
(ipv4->string (bytes 0 0 0 0))
=> "0.0.0.0"
(ipv4->string (bytes 255 255 0 1))
=> "255.255.0.1"
(ipv4->string (bytes 127 0 0 1))
=> "127.0.0.1"
(ipv4->string (bytes 8 8 8 8))
=> "8.8.8.8"
;; ----------------------------------------
(ipv6->string (bytes 32 1 13 184 133 163 0 0 0 0 138 46 3 112 115 52))
=> "2001:db8:85a3::8a2e:370:7334"
(ipv6->string (bytes 38 7 248 176 64 9 8 0 0 0 0 0 0 0 16 14))
=> "2607:f8b0:4009:800::100e"
(ipv6->string (bytes 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255))
=> "::ffff"
(ipv6->string (bytes 255 255 0 0 0 0 0 0 0 0 0 0 0 0 255 255))
=> "ffff::ffff"
;; ----------------------------------------
(compress '(0 0 0 5 5)) => '(:: 5 5)
(compress '(0 5 5)) => '(0 5 5)
(compress '(0 0 5 0 0 5)) => '(:: 5 0 0 5)
(compress '(0 5 0 0 0 5)) => '(0 5 :: 5)
;; ----------------------------------------
((bytes-of-length 5) (bytes 1 2 3 4 5))
(not ((bytes-of-length 5) "moogle"))
;; ----------------------------------------
))

View File

@ -1,6 +1,8 @@
#lang racket/base
(require tests/eli-tester
(prefix-in ip: "ip.rkt")
(prefix-in dns: "dns.rkt")
(prefix-in ucodec: "uri-codec.rkt")
(prefix-in url: "url.rkt")
(prefix-in cgi: "cgi.rkt")
@ -13,7 +15,9 @@
(prefix-in websocket: "websocket.rkt"))
(define (tests)
(test do (url:tests)
(test do (ip:tests)
do (dns:tests)
do (url:tests)
do (ucodec:tests)
do (ucodec:noels-tests)
do (cgi:tests)

View File

@ -43,7 +43,9 @@
(test (combine-url/relative-vec (->vec base) relative)
=> (->vec expected)))
(define (run-tests)
(provide tests)
(module+ main (tests))
(define (tests)
(test
;; Test the current-proxy-servers parameter can be set
(parameterize ([current-proxy-servers '(("http" "proxy.com" 3128))])
@ -373,7 +375,3 @@
))
)
(provide tests)
(module+ main (tests))
(define (tests) (test do (run-tests)))