(load-relative "loadtest.ss") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; url.ss tests ;; (require (lib "url.ss" "net") (lib "uri-codec.ss" "net") (lib "string.ss")) (test "%Pq" uri-decode "%Pq") (test "%P" uri-decode "%P") (test "a=hel%2blo+%e7%88%b8" alist->form-urlencoded '((a . "hel+lo \u7238"))) (test '((a . "hel+lo \u7238")) form-urlencoded->alist (alist->form-urlencoded '((a . "hel+lo \u7238")))) (test "a=hel%2blo;b=good-bye" alist->form-urlencoded '((a . "hel+lo") (b . "good-bye"))) (parameterize ([current-alist-separator-mode 'semi]) (test "a=hel%2blo;b=good-bye" alist->form-urlencoded '((a . "hel+lo") (b . "good-bye")))) (parameterize ([current-alist-separator-mode 'amp]) (test "a=hel%2blo&b=good-bye" alist->form-urlencoded '((a . "hel+lo") (b . "good-bye")))) (test '((a . "hel+lo") (b . "good-bye")) form-urlencoded->alist (alist->form-urlencoded '((a . "hel+lo") (b . "good-bye")))) (parameterize ([current-alist-separator-mode 'amp]) (test '((a . "hel+lo") (b . "good-bye")) form-urlencoded->alist (alist->form-urlencoded '((a . "hel+lo") (b . "good-bye"))))) (test '((a . "hel+lo") (b . "good-bye")) form-urlencoded->alist (parameterize ([current-alist-separator-mode 'amp]) (alist->form-urlencoded '((a . "hel+lo") (b . "good-bye"))))) (parameterize ([current-alist-separator-mode 'semi]) (test '((a . "hel+lo&b=good-bye")) form-urlencoded->alist (parameterize ([current-alist-separator-mode 'amp]) (alist->form-urlencoded '((a . "hel+lo") (b . "good-bye")))))) (parameterize ([current-alist-separator-mode 'amp]) (test '((a . "hel+lo;b=good-bye")) form-urlencoded->alist (parameterize ([current-alist-separator-mode 'semi]) (alist->form-urlencoded '((a . "hel+lo") (b . "good-bye")))))) (test "aNt=hi" alist->form-urlencoded '((aNt . "hi"))) (test '((aNt . "hi")) form-urlencoded->alist (alist->form-urlencoded '((aNt . "hi")))) (test "aNt=hi" alist->form-urlencoded (form-urlencoded->alist "aNt=hi")) (test 'amp-or-semi current-alist-separator-mode) (err/rt-test (current-alist-separator-mode 'bad)) (let ([with-censor (load-relative "censor.ss")]) (with-censor (lambda () ;; Test all ASCII chars (let ([p (let loop ([n 0]) (if (= n 128) null (let ([s (string (char-downcase (integer->char n)))]) (cons (cons (string->symbol s) s) (loop (add1 n))))))]) (test p form-urlencoded->alist (alist->form-urlencoded p)) (let ([l (apply string-append (map cdr p))]) (test l uri-decode (uri-encode l))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; tests adapted from Noel Welsh's original test suite ;; (let () (define-syntax (for stx) (syntax-case stx (code) [(_ (i from to) e) (and (identifier? (syntax code)) (number? (syntax-e (syntax from))) (number? (syntax-e (syntax to)))) (syntax (let loop ([i from]) e (unless (= i to) (loop (+ i 1)))))])) (test "hello" uri-encode "hello") (test "hello%20there" uri-encode "hello there") (let ((pad (lambda (str) (if (= (string-length str) 1) (string-append "0" str) str)))) (for (code 0 127) (if (or (= code 45) (= code 33) (= code 95) (= code 46) (= code 126) (= code 42) (= code 39) (= code 40) (= code 41) (and (<= 48 code) (<= code 57)) ; 0-9 (and (<= 65 code) (<= code 90)) ; A-Z (and (<= 97 code) (<= code 122))) ; a-z (test (string (integer->char code)) uri-encode (string (integer->char code))) (test (string-append "%" (pad (number->string code 16))) uri-encode (string (integer->char code)))))) (test "" alist->form-urlencoded '()) (test "key=hello+there" alist->form-urlencoded '((key . "hello there"))) (test "key1=hi;key2=hello" alist->form-urlencoded '((key1 . "hi") (key2 . "hello"))) (test "key1=hello+there" alist->form-urlencoded '((key1 . "hello there"))) (test "hello" uri-decode "hello") (test "hello there" uri-decode "hello%20there") (let* ((pad (lambda (str) (if (= (string-length str) 1) (string-append "0" str) str))) (uppercase (lambda (str) (string-uppercase! str) str)) (lowercase (lambda (str) (string-lowercase! str) str)) (hexcode (lambda (code) (string-append "%" (pad (number->string code 16)))))) ;; each of the next three of these were going from 0 to 255 in Noel's ;; original test suite. Those fail here, however. (for (code 0 127) (test (string (integer->char code)) uri-decode (uppercase (hexcode code)))) (for (code 0 127) (test (string (integer->char code)) uri-decode (lowercase (hexcode code))))) (for (code 0 127) (test (string (integer->char code)) uri-decode (string (integer->char code)))) ;; form-urlencoded->alist (test '() form-urlencoded->alist "") (test '((key . "value")) form-urlencoded->alist "key=value") (test '((key . "hello there")) form-urlencoded->alist "key=hello+there") (test '((key . "a value")) form-urlencoded->alist "key=a%20value") (test '((key . "")) form-urlencoded->alist "key") (test '((key1 . "value 1") (key2 . "value 2")) form-urlencoded->alist "key1=value+1&key2=value+2")) ;; ;; end Noel's original tests ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (let () (define (test-s->u vec str) (define (string->url/vec str) (url->vec (string->url str))) (define (url/vec->string vec) (url->string (vec->url vec))) (test vec string->url/vec str) (test str url/vec->string vec)) (define (test-c-u/r expected base relative) (define (combine-url/relative-vec x y) (url->vec (combine-url/relative (vec->url x) y))) (test (url->vec expected) combine-url/relative-vec (url->vec base) relative)) (define (vec->url vec) (make-url (vector-ref vec 0) (vector-ref vec 1) (vector-ref vec 2) (vector-ref vec 3) (map (lambda (x) (if (string? x) x (make-path/param (vector-ref x 0) (vector-ref x 1)))) (vector-ref vec 4)) (vector-ref vec 5) (vector-ref vec 6))) (define (url->vec url) (vector (url-scheme url) (url-user url) (url-host url) (url-port url) (map (lambda (x) (if (string? x) x (vector (path/param-path x) (path/param-param x)))) (url-path url)) (url-query url) (url-fragment url))) (test-s->u (vector #f #f #f #f '("") '() #f) "/") (test-s->u (vector #f #f #f #f '() '() #f) "") (test-s->u (vector "http" #f "www.drscheme.org" #f '("") '() #f) "http://www.drscheme.org/") (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '() #f) "http://www.drscheme.org/a/b/c") (test-s->u (vector "http" "robby" "www.drscheme.org" #f (list "a" "b" "c") '() #f) "http://robby@www.drscheme.org/a/b/c") (test-s->u (vector "http" #f "www.drscheme.org" 8080 (list "a" "b" "c") '() #f) "http://www.drscheme.org:8080/a/b/c") (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '() "joe") "http://www.drscheme.org/a/b/c#joe") (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((tim . "")) #f) "http://www.drscheme.org/a/b/c?tim=") (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((tim . "")) "joe") "http://www.drscheme.org/a/b/c?tim=#joe") (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((tim . "tim")) "joe") "http://www.drscheme.org/a/b/c?tim=tim#joe") (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((tam . "tom")) "joe") "http://www.drscheme.org/a/b/c?tam=tom#joe") (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((tam . "tom") (pam . "pom")) "joe") "http://www.drscheme.org/a/b/c?tam=tom;pam=pom#joe") (parameterize ([current-alist-separator-mode 'semi]) (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((tam . "tom") (pam . "pom")) "joe") "http://www.drscheme.org/a/b/c?tam=tom;pam=pom#joe")) (parameterize ([current-alist-separator-mode 'amp]) (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((tam . "tom") (pam . "pom")) "joe") "http://www.drscheme.org/a/b/c?tam=tom&pam=pom#joe")) (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" #("c" "b")) '() #f) "http://www.drscheme.org/a/b/c;b") (test-s->u (vector "http" #f "www.drscheme.org" #f (list #("a" "x") "b" #("c" "b")) '() #f) "http://www.drscheme.org/a;x/b/c;b") ;; test unquoting for % (test-s->u (vector "http" #f "www.drscheme.org" #f (list "a" "b" "c") '((ti#m . "")) "jo e") "http://www.drscheme.org/a/b/c?ti%23m=#jo%20e") (test-s->u (vector "http" #f "www.drscheme.org" #f (list #("a " " a") " b " " c ") '() #f) "http://www.drscheme.org/a ; a/ b / c ") (test-s->u (vector "http" "robb y" "www.drscheme.org" #f '("") '() #f) "http://robb%20y@www.drscheme.org/") (let ([empty-url (make-url #f #f #f #f '() '() #f)]) (test-c-u/r (string->url "http://www.drscheme.org") empty-url "http://www.drscheme.org") (test-c-u/r (string->url "http://www.drscheme.org") (string->url "http://www.drscheme.org") "")) (test-c-u/r (string->url "http://www.mzscheme.org") (string->url "http://www.drscheme.org/") "http://www.mzscheme.org") (test-c-u/r (string->url "http://www.drscheme.org/index.html") (string->url "http://www.drscheme.org/") "index.html") (test-c-u/r (string->url "http://www.drscheme.org/index.html") (string->url "http://www.drscheme.org/") "/index.html") (test-c-u/r (string->url "http://www.drscheme.org/index.html") (string->url "http://www.drscheme.org/a/b/c/") "/index.html") (test-c-u/r (string->url "http://www.drscheme.org/a/b/index.html") (string->url "http://www.drscheme.org/a/b/c") "index.html") (test-c-u/r (string->url "http://www.drscheme.org/a/b/c/index.html") (string->url "http://www.drscheme.org/a/b/c/") "index.html") (test-c-u/r (string->url "http://www.drscheme.org/a/b/d/index.html") (string->url "http://www.drscheme.org/a/b/c") "d/index.html") (test-c-u/r (string->url "http://www.drscheme.org/a/b/c/d/index.html") (string->url "http://www.drscheme.org/a/b/c/") "d/index.html") (test-c-u/r (string->url "file:///a/b/c/d/index.html") (string->url "file:///a/b/c/") "d/index.html") (test-c-u/r (string->url "file:///a/b/d/index.html") (string->url "file:///a/b/c") "d/index.html") ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; other net tests ;; (require (lib "base64.ss" "net") (lib "qp.ss" "net") (lib "port.ss")) (define tricky-strings (let ([dir (collection-path "tests" "mzscheme")]) (list (make-bytes 200 32) (make-bytes 200 9) (make-bytes 200 (char->integer #\x)) (list->bytes (let loop ([i 0]) (if (= i 256) null (cons i (loop (add1 i)))))) ;; Something that doesn't end with a LF: (bytes-append (with-input-from-file (build-path dir "net.ss") (lambda () (read-bytes 500))) #"xxx") ;; CRLF: (regexp-replace #rx#"\n" (with-input-from-file (build-path dir "net.ss") (lambda () (read-bytes 500))) #"\r\n")))) (define (check-same encode decode port line-rx max-w) (let ([p (open-output-bytes)]) (copy-port port p) (let ([bytes (get-output-bytes p)] [r (open-output-bytes)]) (encode (open-input-bytes bytes) r) (let ([p (open-input-bytes (get-output-bytes r))]) (let loop () (let ([l (read-bytes-line p 'any)]) (unless (eof-object? l) (unless (<= (bytes-length l) max-w) (test encode "line too long" l)) (let ([m (regexp-match-positions line-rx l)]) (unless (and m (= (bytes-length l) (cdar m))) (test encode 'bad-line l))) (loop)))) (let ([q (open-output-bytes)]) (decode (open-input-bytes (get-output-bytes r)) q) (unless (equal? (get-output-bytes q) bytes) (with-output-to-file "/tmp/x0" (lambda () (display (get-output-bytes r))) 'truncate) (with-output-to-file "/tmp/x1" (lambda () (display (get-output-bytes q))) 'truncate) (with-output-to-file "/tmp/x2" (lambda () (display bytes)) 'truncate) (error 'decode "failed"))))))) (define (check-same-file encode decode file line-rx max-w) ;; This "test" is really just a progress report: (test #t list? (list file encode)) (call-with-input-file file (lambda (p) (check-same encode decode p line-rx max-w)))) (define (check-same-all encode decode line-rx max-w) (for-each (lambda (tricky-string) (check-same encode decode (open-input-bytes tricky-string) line-rx max-w)) tricky-strings) (parameterize ([current-pseudo-random-generator (make-pseudo-random-generator)]) (random-seed 17) (let ([dir (collection-path "tests" "mzscheme")]) (for-each (lambda (p) (when (regexp-match #rx"[.]ss$" (path->string p)) (unless (or (positive? (random 10)) ; check random 1/10 of files (equal? (path->string p) "flat.ss")) (check-same-file encode decode (build-path dir p) line-rx max-w)))) (directory-list dir))))) (check-same-all (lambda (i o) (qp-encode-stream i o)) qp-decode-stream #rx#"^(|[\t \41-\176]*[\41-\176]+)$" 76) (check-same-all base64-encode-stream base64-decode-stream #rx#"^[0-9a-zA-Z+=/]*$" 72) (report-errs)