#lang imperative-syndicate/test-implementation
;; Box-and-client

(test-case
    [(message-struct set-box (new-value))
     (assertion-struct box-state (value))

     (spawn (field [current-value 0])
            (assert (box-state (current-value)))
            (stop-when-true (= (current-value) 3)
                            (displayln "box: terminating"))
            (on (message (set-box $new-value))
                (printf "box: taking on new-value ~v\n" new-value)
                (current-value new-value)))

     (spawn (stop-when (retracted (observe (set-box _)))
              (displayln "client: box has gone"))
            (on (asserted (box-state $v))
                (printf "client: learned that box's value is now ~v\n" v)
                (send! (set-box (+ v 1)))))]
  no-crashes
  (expected-output (list "client: learned that box's value is now 0"
                         "box: taking on new-value 1"
                         "client: learned that box's value is now 1"
                         "box: taking on new-value 2"
                         "client: learned that box's value is now 2"
                         "box: taking on new-value 3"
                         "box: terminating"
                         "client: box has gone")))
