#lang scheme/base
(require (planet schematics/schemeunit:3) "pa2.ss")
(require (planet schematics/schemeunit:3/text-ui))
;; When first you run this, it will fetch and install schemeunit automatically.

;; For use in tests. True if the correct error message is raised; false otherwise.
(define read-and-parse-string (compose parse read open-input-string))
(define read-and-eval-string (compose calc read-and-parse-string))
(define (try-to-parse input-string)
  (lambda () (read-and-parse-string input-string)))
(define (try-to-eval input-string)
  (lambda () (read-and-eval-string input-string)))

;; For use in tests. True if the correct error message is raised; false otherwise.
(define (expect-error msg)
  (lambda (exn) (string=? (exn-message exn) msg)))

(define my-value-is-7
  "{with {{x 2} {y 3}}
     {with {{z {+ x y}}}
       {+ x z}}}")

(define pa2-tests
  (test-suite
   "pa2"
   ;; Tests that should generate errors.
   (check-exn (expect-error "parse: unexpected keyword")
              (try-to-parse "with"))
   (check-exn (expect-error "parse: unexpected empty list")
              (try-to-parse "{}"))
   (check-exn (expect-error "parse: malformed with expression")
              (try-to-parse "{with}"))
   (check-exn (expect-error "parse: invalid binary operator: foo")
              (try-to-parse "{foo 1 2}"))
   (check-exn (expect-error "parse: wrong number of arguments to binary operator")
              (try-to-parse "{+ 1}"))
   (check-exn (expect-error "parse: invalid datatype in input")
              (try-to-parse "#t"))
   (check-exn (expect-error "parse: expected a list of bindings")
              (try-to-parse "{with x x}"))
   (check-exn (expect-error "parse: expected list in binding of with expression")
              (try-to-parse "{with {x} x}"))
   (check-exn (expect-error "parse: expected (id val) in with expression")
              (try-to-parse "{with {{x}} x}"))
   (check-exn (expect-error "parse: identifiers must be symbols")
              (try-to-parse "{with {{1 2}} x}"))
   (check-exn (expect-error "parse: cannot bind a value to a reserved symbol")
              (try-to-parse "{with {{with 2}} x}"))
   (check-exn (expect-error "parse: duplicate bindings for identifier")
              (try-to-parse "{with {{x 1} {x 2}} x}"))
   (check-exn (expect-error "calc: free identifier: x")
              (try-to-eval "x"))

   ;; Tests that should succeed. You should write a lot more of these!
   (check-equal? (read-and-eval-string my-value-is-7) 7)
   ))

(run-tests pa2-tests)
