future-test.ss
(module future-test mzscheme
  
  (require
   (lib "contract.ss")
   (planet "test.ss" ("schematics" "schemeunit.plt" 2 0))
   (file "base.ss")
   (file "future.ss")
   )
  
  (provide 
   future-tests
   )
  
  (define future-tests
    (test-suite
     "future.ss"
     
     (test-equal?
      "future returns initial value"
      ((make-future 10))
      10)
     
     (test-true
      "future returns procedure if make-dependency omitted"
      (andmap
       procedure?
       (let* ([counter 0]
              [get-counter
               (lambda ()
                 (set! counter (add1 counter))
                 counter)]
              [f (make-future 
                  (lambda ()
                    (set! counter (add1 counter))
                    counter))])
         (list (f) (f) (f)))))

     (test-equal?
      "future's value can be set destructively"
      (let ([f (make-future 10)])
        (f 20)
        (f))
      20)
     
     (test-equal?
      "future's value can be set"
      (let ([f (make-future 10)])
        (f 20)
        (f 30)
        (f))
      30)
     
     (test-equal?
      "future's value is scoped according to epoch"
      (let ([f (make-future 10)])
        (next-future-scope
         (f 30))
        (f))
      10)
     
     (test-case
      "futures' values change in sync with scope"
      (let ([a (make-future 10)]
            [b (make-future 10)]
            [c (make-future 10)])
        (next-future-scope
         (a 20)
         (check-equal? (a) 20)
         (check-equal? (b) 10)
         (check-equal? (c) 10))
        (b 20)
        (check-equal? (a) 10)
        (check-equal? (b) 20)
        (check-equal? (c) 10)
        (next-future-scope
         (c 20)
         (check-equal? (a) 10)
         (check-equal? (b) 20)
         (check-equal? (c) 20)
         (next-future-scope
          (check-equal? (a) 10)
          (check-equal? (b) 20)
          (check-equal? (c) 20)))))
     
     (test-case
      "future's values change in accordance with continuation jumps"
      (let ([a (make-future 10)])
        (check-equal? (a) 10)
        (let/cc k
          (a 20)
          (k))
        (check-equal? (a) 20)
        (next-future-scope
         (let/cc k
           (a 30)
           (k)))
        (check-equal? (a) 20)))
     
     ))
  
  )