instaweb-test.ss
;;;
;;; Time-stamp: <2007-11-16 17:37:04 us>
;;;
;;; Copyright (C) by Noel Welsh.
;;;

;;; This library is free software; you can redistribute it
;;; and/or modify it under the terms of the GNU Lesser
;;; General Public License as published by the Free Software
;;; Foundation; either version 2.1 of the License, or (at
;;; your option) any later version.

;;; This library is distributed in the hope that it will be
;;; useful, but WITHOUT ANY WARRANTY; without even the
;;; implied warranty of MERCHANTABILITY or FITNESS FOR A
;;; PARTICULAR PURPOSE.  See the GNU Lesser General Public
;;; License for more details.

;;; You should have received a copy of the GNU Lesser
;;; General Public License along with this library; if not,
;;; write to the Free Software Foundation, Inc., 59 Temple
;;; Place, Suite 330, Boston, MA 02111-1307 USA

;;; Author: Noel Welsh <noelwelsh@yahoo.com>
;;
;;
;; Commentary:

#lang scheme/base 

(require (for-syntax scheme/base))

(require mzlib/etc
         net/url)

(require (planet "port.ss" ("schematics" "port.plt" 1))
         (planet "test.ss" ("schematics" "schemeunit.plt" 2)))

(require (file "instaweb.ss"))

(provide instaweb-tests)

(define (make-dummy)
  (with-output-to-file "dummy.ss"
    (lambda ()
      (write
       '(module dummy mzscheme
          (require (lib "servlet.ss" "web-server"))
          (provide interface-version timeout start)
          (define interface-version 'v1)
          (define timeout +inf.0)
          (define (start initial-request)
            (make-response/full
             200
             "OK"
             (current-seconds)
             #"text/plain"
             '()
             '("foo\r\n"))))))
    #:exists 'replace))

(define-syntax spawn-instaweb
  (syntax-rules ()
    [(spawn-instaweb args ...)
     (begin (sleep 1)
            (let ([server (thread (lambda () 
                                    (instaweb args ...)))])
              (sleep 1)
              server))]))

(define (read-content url)
  (get-pure-port (string->url url)))

(define here (this-expression-source-directory))

(define instaweb-tests
  (test-suite "All tests for instaweb"
    
    (test-case "Server listens on specified port and IP"
      (before
       (make-dummy)
       (let ([server (spawn-instaweb #:port 4567 #:servlet-path "dummy.ss")]
             [content (read-content "http://127.0.0.1:4567/servlets/dummy.ss")])
         (check string=? (port->string content) "foo\r\n")
         ;; Check the server is not listening on other ports
         (check-exn exn:fail:network?
           (lambda ()
             (read-content "http://127.0.0.1:8123/servlets/dummy.ss")))
         (kill-thread server))))
    
    (test-case "Instaweb stops reading if input port returns eof"
      (before
       (make-dummy)
       (let* ([op (open-output-string)]
              [server
               (thread
                (lambda ()
                  (parameterize
                      ((current-input-port (open-input-string ""))
                       (current-output-port op))
                    (instaweb #:port 4567
                              #:listen-ip "127.0.0.1"
                              #:servlet-path "dummy.ss"))))])
         (kill-thread server)
         (let ((content (get-output-string op)))
           (display content)
           (check <=
                  (string-length content)
                  218)))))
    
    (test-case "Instaweb reads default htdocs-path"
      (around
       (begin (make-directory "htdocs")
              (with-output-to-file "htdocs/dummy.txt"
                (lambda () (display "boo-yah!"))))
       (let ([server (spawn-instaweb #:servlet-path "dummy.ss")])
         (check-equal?
          (port->string (read-content "http://127.0.0.1:8765/dummy.txt"))
          "boo-yah!")
         (kill-thread server))
       (begin (delete-file "htdocs/dummy.txt")
              (delete-directory "htdocs"))))
    
    (test-case "Instaweb reads specified htdocs-path"
      (around
       (begin (make-directory "public-htdocs")
              (with-output-to-file "public-htdocs/dummy.txt"
                (lambda () (display "boo-yah!"))))
       (let ([server (spawn-instaweb #:port 4320
                                     #:servlet-path "dummy.ss"
                                     #:htdocs-path '("public-htdocs"))])
         (check-equal?
          (port->string (read-content "http://127.0.0.1:4320/"))
          "foo\r\n")
         (check-equal?
          (port->string (read-content "http://127.0.0.1:4320/dummy.txt"))
          "boo-yah!")
         (kill-thread server))
       (begin (delete-file "public-htdocs/dummy.txt")
              (delete-directory "public-htdocs"))))
    
    ))