diff --git a/syndicate/.gitignore b/syndicate/.gitignore new file mode 100644 index 0000000..724bbe1 --- /dev/null +++ b/syndicate/.gitignore @@ -0,0 +1 @@ +compiled/ diff --git a/syndicate/info.rkt b/syndicate/info.rkt new file mode 100644 index 0000000..199602a --- /dev/null +++ b/syndicate/info.rkt @@ -0,0 +1,2 @@ +#lang setup/infotab +(define collection "imperative-syndicate") diff --git a/syndicate/pattern.rkt b/syndicate/pattern.rkt index b747d1b..bce921f 100644 --- a/syndicate/pattern.rkt +++ b/syndicate/pattern.rkt @@ -46,7 +46,7 @@ (define (discard-id? stx) (and (identifier? stx) - (free-transformer-identifier=? #'_ stx))) + (free-identifier=? #'_ stx))) (define (id-value stx) (and (identifier? stx) @@ -54,7 +54,7 @@ (define (list-id? stx) (and (identifier? stx) - (free-transformer-identifier=? #'list stx))) + (free-identifier=? #'list stx))) (define (analyse-pattern stx) (syntax-case stx ($) diff --git a/syndicate/syntax.rkt b/syndicate/syntax.rkt index b77f8a6..c6b1ee3 100644 --- a/syndicate/syntax.rkt +++ b/syndicate/syntax.rkt @@ -577,378 +577,3 @@ (define (current-adhoc-assertions) (actor-adhoc-assertions (current-actor))) - -;;--------------------------------------------------------------------------- - -(module+ test - (require "test.rkt") - - (test-case - ;; See .../syndicate/examples/actor/example-during-criterion-shapshotting.rkt - [(struct foo (x y) #:prefab) - (spawn (field [x 123]) - (assert (foo (x) 999)) - (during (foo (x) $v) - (printf "x=~a v=~a\n" (x) v) - (when (= (x) 123) (x 124)) - (on-stop (printf "finally for x=~a v=~a\n" (x) v))))] - no-crashes - (expected-output "x=123 v=999" - "x=124 v=999" - "finally for x=124 v=999")) - - (test-case - ;; Goal: no matter the circumstances (e.g. exception in a - ;; stop script), we will never retract an assertion more or - ;; fewer than the correct number of times. - [(spawn #:name 'supply - #:assertions ['marker] - (assert 'marker) ;; NB this is the change wrt the test case immediately below - (error 'test-case "Deliberate error")) - - (spawn (on (asserted 'marker) (printf "marker appeared\n")) - (on (retracted 'marker) (printf "marker disappeared\n")))] - (it "should crash deliberately" (actor-died? 'supply "Deliberate error")) - (expected-output "marker appeared" - "marker disappeared")) - - (test-case - ;; Goal: no matter the circumstances (e.g. exception in a - ;; stop script), we will never retract an assertion more or - ;; fewer than the correct number of times. - [(spawn #:name 'supply - #:assertions ['marker] - (error 'test-case "Deliberate error")) - - (spawn (on (asserted 'marker) (printf "marker appeared\n")) - (on (retracted 'marker) (printf "marker disappeared\n")))] - (it "should crash deliberately" (actor-died? 'supply "Deliberate error")) - (expected-output "marker appeared" - "marker disappeared")) - - (test-case - ;; Goal: no matter the circumstances (e.g. exception in a - ;; stop script), we will never retract an assertion more or - ;; fewer than the correct number of times. - ;; - ;; Test cleanup after exception in stop script - [(assertion-struct layer (name)) - (spawn #:name 'crasher - (define root-facet (current-facet)) - (assert (layer 'outer)) - (on-start (react (assert (layer 'middle)) - (on-start (flush!) (flush!) (stop-facet root-facet)) - (on-stop (/ 1 0)) - (on-start (react (assert (layer 'inner))))))) - (spawn (on (retracted (layer $x)) (printf "~a gone\n" x)))] - (it "should crash with division by zero" (actor-died? 'crasher "division by zero")) - ;; a permutation of these lines is acceptable: - (expected-output "middle gone" - "inner gone" - "outer gone")) - - (begin ;; Suite of four related tests. - ;; See .../syndicate/examples/actor/example-responsibility-transfer-2.rkt - - (test-case - [(spawn #:name 'factory-1 - (on (asserted (list 'X 1)) - (spawn #:name 'service-1 - #:assertions [(observe (list 'X 1))] ;; (A) - (stop-when (retracted (list 'X 1))) ;; (B) - (on (message 'dummy))) - (stop-current-facet))) - (spawn (on (asserted (observe (list 'X $supplier))) - (printf "Supply ~v asserted.\n" supplier) - (assert! (list 'X supplier))) - (on (retracted (observe (list 'X $supplier))) - (printf "Supply ~v retracted.\n" supplier)))] - no-crashes - (expected-output "Supply 1 asserted.")) - - (test-case - [(spawn #:name 'factory-1 - (on (asserted (list 'X 1)) - (spawn #:name 'service-1 - ;; #:assertions [(observe (list 'X 1))] ;; (A) - (stop-when (retracted (list 'X 1))) ;; (B) - (on (message 'dummy))) - (stop-current-facet))) - (spawn (on (asserted (observe (list 'X $supplier))) - (printf "Supply ~v asserted.\n" supplier) - (assert! (list 'X supplier))) - (on (retracted (observe (list 'X $supplier))) - (printf "Supply ~v retracted.\n" supplier)))] - no-crashes - (expected-output "Supply 1 asserted." - "Supply 1 retracted." - "Supply 1 asserted.")) - - (test-case - [(spawn #:name 'factory-1 - (on (asserted (list 'X 1)) - (spawn #:name 'service-1 - #:assertions [(observe (list 'X 1))] ;; (A) - ;; (stop-when (retracted (list 'X 1))) ;; (B) - (on (message 'dummy))) - (stop-current-facet))) - (spawn (on (asserted (observe (list 'X $supplier))) - (printf "Supply ~v asserted.\n" supplier) - (assert! (list 'X supplier))) - (on (retracted (observe (list 'X $supplier))) - (printf "Supply ~v retracted.\n" supplier)))] - no-crashes - (expected-output "Supply 1 asserted." - "Supply 1 retracted.")) - - (test-case - [(spawn #:name 'factory-1 - (on (asserted (list 'X 1)) - (spawn #:name 'service-1 - ;; #:assertions [(observe (list 'X 1))] ;; (A) - ;; (stop-when (retracted (list 'X 1))) ;; (B) - (on (message 'dummy))) - (stop-current-facet))) - (spawn (on (asserted (observe (list 'X $supplier))) - (printf "Supply ~v asserted.\n" supplier) - (assert! (list 'X supplier))) - (on (retracted (observe (list 'X $supplier))) - (printf "Supply ~v retracted.\n" supplier)))] - no-crashes - (expected-output "Supply 1 asserted." - "Supply 1 retracted.")) - - ) - - (test-case - ;; See .../syndicate/examples/actor/example-responsibility-transfer-1.rkt - [(spawn #:name 'demand-watcher - (during/spawn 'demand - #:name (gensym 'intermediate-demand-asserter) - (assert 'intermediate-demand))) - - (spawn #:name 'intermediate-demand-watcher - (during/spawn 'intermediate-demand - #:name (gensym 'supply-asserter) - (assert 'supply))) - - (spawn* #:name 'driver - (react (on (asserted 'supply) (displayln "Supply asserted.")) - (on (retracted 'supply) (displayln "Supply retracted."))) - (until (asserted (observe 'demand))) - (displayln "Asserting demand.") - (assert! 'demand) - (until (asserted 'supply)) - (displayln "Glitching demand.") - (retract! 'demand) - (flush!) - (assert! 'demand) - (displayln "Demand now steady."))] - no-crashes - (expected-output "Asserting demand." - "Supply asserted." - "Glitching demand." - "Demand now steady." - "Supply retracted." - "Supply asserted.")) - - (test-case - [(assertion-struct one-plus (n m)) - (spawn #:name 'add1-server - (during/spawn (observe (one-plus $n _)) - #:name (list 'solving 'one-plus n) - (assert (one-plus n (+ n 1))))) - (spawn #:name 'client-process - (stop-when (asserted (one-plus 3 $value)) - (printf "1 + 3 = ~a\n" value)))] - no-crashes - (expected-output "1 + 3 = 4")) - - (test-case - ;; .../racket/syndicate/examples/actor/example-partial-retraction.rkt - [(struct ready (what) #:prefab) - (struct entry (key val) #:prefab) - - (spawn (assert (ready 'listener)) - (on (asserted (entry $key _)) - (printf "key ~v asserted\n" key) - (until (retracted (entry key _)) - (on (asserted (entry key $value)) - (printf "add binding: ~v -> ~v\n" key value)) - (on (retracted (entry key $value)) - (printf "del binding: ~v -> ~v\n" key value))) - (printf "key ~v retracted\n" key))) - - (spawn (assert (ready 'other-listener)) - (during (entry $key _) - (printf "(other-listener) key ~v asserted\n" key) - (on-stop (printf "(other-listener) key ~v retracted\n" key)) - (during (entry key $value) - (printf "(other-listener) ~v ---> ~v\n" key value) - (on-stop (printf "(other-listener) ~v -/-> ~v\n" key value))))) - - (define (pause) - (displayln "pause") - (define token (gensym 'pause)) ;; FIXME:: If we use the same token every time, need epochs! - (until (asserted (ready token)) - (assert (ready token)))) - - (spawn* (until (asserted (ready 'listener))) - (until (asserted (ready 'other-listener))) - (assert! (entry 'a 1)) - (assert! (entry 'a 2)) - (assert! (entry 'b 3)) - (assert! (entry 'c 33)) - (assert! (entry 'a 4)) - (assert! (entry 'a 5)) - (pause) - (retract! (entry 'a 2)) - (retract! (entry 'c 33)) - (assert! (entry 'a 9)) - (pause) - (local-require "bag.rkt") - (for [(a (in-bag (current-adhoc-assertions)))] - (local-require racket/match) - (match a - [(entry 'a _) (retract! a)] - [_ (void)])) - ;; ^ (retract! (entry 'a ?)) - (pause))] - no-crashes - ;; Within the following, some permutations are acceptable: - #;(expected-output - "pause" - "pause" - "(other-listener) key 'a asserted" - "(other-listener) key 'c asserted" - "(other-listener) key 'b asserted" - "(other-listener) 'a ---> 4" - "(other-listener) 'a ---> 1" - "(other-listener) 'a ---> 2" - "(other-listener) 'a ---> 5" - "(other-listener) 'c ---> 33" - "(other-listener) 'b ---> 3" - "key 'a asserted" - "key 'c asserted" - "key 'b asserted" - "add binding: 'a -> 4" - "add binding: 'a -> 1" - "add binding: 'a -> 2" - "add binding: 'a -> 5" - "add binding: 'c -> 33" - "add binding: 'b -> 3" - "pause" - "del binding: 'a -> 2" - "del binding: 'c -> 33" - "add binding: 'a -> 9" - "key 'c retracted" - "(other-listener) 'a ---> 9" - "(other-listener) 'a -/-> 2" - "(other-listener) 'c -/-> 33" - "(other-listener) key 'c retracted" - "del binding: 'a -> 1" - "del binding: 'a -> 9" - "del binding: 'a -> 5" - "del binding: 'a -> 4" - "key 'a retracted" - "(other-listener) 'a -/-> 1" - "(other-listener) 'a -/-> 9" - "(other-listener) 'a -/-> 5" - "(other-listener) 'a -/-> 4" - "(other-listener) key 'a retracted" - "del binding: 'b -> 3" - "key 'b retracted" - "(other-listener) 'b -/-> 3" - "(other-listener) key 'b retracted" - )) - - (let ((N 100000)) - (test-case - ;; Rough message send speed test - [(spawn (on (message $v) - (if (= v N) - (stop-current-facet) - (send! (+ v 1)))) - (on-start (send! 0)))] - no-crashes - (it "should be fairly quick" - (log-info "Rough message send speed: ~a msgs in ~a ms = ~a Hz" - N - (test-run-time) - (/ N (/ (test-run-time) 1000.0)))))) - - (test-case - ;; Tests that pending actions are abandoned during a turn in which there is an exception - [(message-struct stage (n)) - - (spawn #:name 'actor0 - (on (message (stage 0)) - (send! (stage 1))) - - (on (message (stage 2)) - (send! (stage 3)) - (/ 1 0) - (send! (stage 3)))) - - (spawn #:name 'main - (on (message (stage $v)) - (printf "Got message ~v\n" v)) - (on-start - (until (asserted (observe (stage 0)))) - (send! (stage 0)) - (until (message (stage 1))) - (send! (stage 2))))] - (it "should involve one crash" (actor-died? 'actor0 "division by zero")) - (expected-output "Got message 0" - "Got message 1" - "Got message 2")) - - (test-case - ;; Box-and-client - [(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 "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")) - - (let ((N 25000)) - (test-case - ;; Box-and-client speed test - [(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) N)) - (on (message (set-box $new-value)) - (current-value new-value))) - (spawn (stop-when (retracted (observe (set-box _)))) - (on (asserted (box-state $v)) - (send! (set-box (+ v 1)))))] - no-crashes - (expected-output) - (it "should be reasonably quick" - (log-info "Rough box-and-client speed: ~a cycles in ~a ms = ~a Hz" - N - (test-run-time) - (/ N (/ (test-run-time) 1000.0)))))) - ) diff --git a/syndicate/test.rkt b/syndicate/test-implementation.rkt similarity index 96% rename from syndicate/test.rkt rename to syndicate/test-implementation.rkt index a14a46e..c1c4bc6 100644 --- a/syndicate/test.rkt +++ b/syndicate/test-implementation.rkt @@ -20,7 +20,13 @@ expected-output run-syndicate-test! - log-test-result!) + log-test-result! + + (all-from-out racket/base) + (all-from-out "dataspace.rkt") + (all-from-out "syntax.rkt")) + +(module reader syntax/module-reader imperative-syndicate/test-implementation) (require racket/exn) (require racket/match) @@ -28,6 +34,7 @@ (require "bag.rkt") (require "dataspace.rkt") +(require "syntax.rkt") (require (for-syntax racket/base)) (require (for-syntax syntax/srcloc)) diff --git a/syndicate/test/core/abandon-actions-on-exn.rkt b/syndicate/test/core/abandon-actions-on-exn.rkt new file mode 100644 index 0000000..3450f2b --- /dev/null +++ b/syndicate/test/core/abandon-actions-on-exn.rkt @@ -0,0 +1,27 @@ +#lang imperative-syndicate/test-implementation +;; Tests that pending actions are abandoned during a turn in which there is an exception + +(test-case + [(message-struct stage (n)) + + (spawn #:name 'actor0 + (on (message (stage 0)) + (send! (stage 1))) + + (on (message (stage 2)) + (send! (stage 3)) + (error 'test-case "Deliberate error") + (send! (stage 3)))) + + (spawn #:name 'main + (on (message (stage $v)) + (printf "Got message ~v\n" v)) + (on-start + (until (asserted (observe (stage 0)))) + (send! (stage 0)) + (until (message (stage 1))) + (send! (stage 2))))] + (it "should involve one crash" (actor-died? 'actor0 "Deliberate error")) + (expected-output "Got message 0" + "Got message 1" + "Got message 2")) diff --git a/syndicate/test/core/correct-retraction-on-exn.rkt b/syndicate/test/core/correct-retraction-on-exn.rkt new file mode 100644 index 0000000..ddb3841 --- /dev/null +++ b/syndicate/test/core/correct-retraction-on-exn.rkt @@ -0,0 +1,44 @@ +#lang imperative-syndicate/test-implementation +;; Goal: no matter the circumstances (e.g. exception in a stop +;; script), we will never retract an assertion more or fewer than the +;; correct number of times. + +(test-case + [(spawn #:name 'supply + #:assertions ['marker] + (assert 'marker) ;; NB this is the change wrt the test case immediately below + (error 'test-case "Deliberate error")) + + (spawn (on (asserted 'marker) (printf "marker appeared\n")) + (on (retracted 'marker) (printf "marker disappeared\n")))] + (it "should crash deliberately" (actor-died? 'supply "Deliberate error")) + (expected-output "marker appeared" + "marker disappeared")) + +(test-case + [(spawn #:name 'supply + #:assertions ['marker] + (error 'test-case "Deliberate error")) + + (spawn (on (asserted 'marker) (printf "marker appeared\n")) + (on (retracted 'marker) (printf "marker disappeared\n")))] + (it "should crash deliberately" (actor-died? 'supply "Deliberate error")) + (expected-output "marker appeared" + "marker disappeared")) + +(test-case + ;; Test cleanup after exception in stop script + [(assertion-struct layer (name)) + (spawn #:name 'crasher + (define root-facet (current-facet)) + (assert (layer 'outer)) + (on-start (react (assert (layer 'middle)) + (on-start (flush!) (flush!) (stop-facet root-facet)) + (on-stop (error 'test-case "Deliberate error")) + (on-start (react (assert (layer 'inner))))))) + (spawn (on (retracted (layer $x)) (printf "~a gone\n" x)))] + (it "should crash deliberately" (actor-died? 'crasher "Deliberate error")) + ;; a permutation of these lines is acceptable: + (expected-output "middle gone" + "inner gone" + "outer gone")) diff --git a/syndicate/test/core/during-criterion-snapshotting.rkt b/syndicate/test/core/during-criterion-snapshotting.rkt new file mode 100644 index 0000000..ad83397 --- /dev/null +++ b/syndicate/test/core/during-criterion-snapshotting.rkt @@ -0,0 +1,15 @@ +#lang imperative-syndicate/test-implementation +;; See .../syndicate/examples/actor/example-during-criterion-shapshotting.rkt + +(test-case + [(struct foo (x y) #:prefab) + (spawn (field [x 123]) + (assert (foo (x) 999)) + (during (foo (x) $v) + (printf "x=~a v=~a\n" (x) v) + (when (= (x) 123) (x 124)) + (on-stop (printf "finally for x=~a v=~a\n" (x) v))))] + no-crashes + (expected-output "x=123 v=999" + "x=124 v=999" + "finally for x=124 v=999")) diff --git a/syndicate/test/core/partial-retraction.rkt b/syndicate/test/core/partial-retraction.rkt new file mode 100644 index 0000000..91e3865 --- /dev/null +++ b/syndicate/test/core/partial-retraction.rkt @@ -0,0 +1,100 @@ +#lang imperative-syndicate/test-implementation +;; See .../racket/syndicate/examples/actor/example-partial-retraction.rkt +;; TODO: deal with permissible permutations in the output + +(test-case + [(struct ready (what) #:prefab) + (struct entry (key val) #:prefab) + + (spawn (assert (ready 'listener)) + (on (asserted (entry $key _)) + (printf "key ~v asserted\n" key) + (until (retracted (entry key _)) + (on (asserted (entry key $value)) + (printf "add binding: ~v -> ~v\n" key value)) + (on (retracted (entry key $value)) + (printf "del binding: ~v -> ~v\n" key value))) + (printf "key ~v retracted\n" key))) + + (spawn (assert (ready 'other-listener)) + (during (entry $key _) + (printf "(other-listener) key ~v asserted\n" key) + (on-stop (printf "(other-listener) key ~v retracted\n" key)) + (during (entry key $value) + (printf "(other-listener) ~v ---> ~v\n" key value) + (on-stop (printf "(other-listener) ~v -/-> ~v\n" key value))))) + + (define (pause) + (displayln "pause") + (define token (gensym 'pause)) ;; FIXME:: If we use the same token every time, need epochs! + (until (asserted (ready token)) + (assert (ready token)))) + + (spawn* (until (asserted (ready 'listener))) + (until (asserted (ready 'other-listener))) + (assert! (entry 'a 1)) + (assert! (entry 'a 2)) + (assert! (entry 'b 3)) + (assert! (entry 'c 33)) + (assert! (entry 'a 4)) + (assert! (entry 'a 5)) + (pause) + (retract! (entry 'a 2)) + (retract! (entry 'c 33)) + (assert! (entry 'a 9)) + (pause) + (local-require "../../bag.rkt") + (for [(a (in-bag (current-adhoc-assertions)))] + (local-require racket/match) + (match a + [(entry 'a _) (retract! a)] + [_ (void)])) + ;; ^ (retract! (entry 'a ?)) + (pause))] + no-crashes + ;; Within the following, some permutations are acceptable: + #;(expected-output + "pause" + "pause" + "(other-listener) key 'a asserted" + "(other-listener) key 'c asserted" + "(other-listener) key 'b asserted" + "(other-listener) 'a ---> 4" + "(other-listener) 'a ---> 1" + "(other-listener) 'a ---> 2" + "(other-listener) 'a ---> 5" + "(other-listener) 'c ---> 33" + "(other-listener) 'b ---> 3" + "key 'a asserted" + "key 'c asserted" + "key 'b asserted" + "add binding: 'a -> 4" + "add binding: 'a -> 1" + "add binding: 'a -> 2" + "add binding: 'a -> 5" + "add binding: 'c -> 33" + "add binding: 'b -> 3" + "pause" + "del binding: 'a -> 2" + "del binding: 'c -> 33" + "add binding: 'a -> 9" + "key 'c retracted" + "(other-listener) 'a ---> 9" + "(other-listener) 'a -/-> 2" + "(other-listener) 'c -/-> 33" + "(other-listener) key 'c retracted" + "del binding: 'a -> 1" + "del binding: 'a -> 9" + "del binding: 'a -> 5" + "del binding: 'a -> 4" + "key 'a retracted" + "(other-listener) 'a -/-> 1" + "(other-listener) 'a -/-> 9" + "(other-listener) 'a -/-> 5" + "(other-listener) 'a -/-> 4" + "(other-listener) key 'a retracted" + "del binding: 'b -> 3" + "key 'b retracted" + "(other-listener) 'b -/-> 3" + "(other-listener) key 'b retracted" + )) diff --git a/syndicate/test/core/responsibility-transfer-1.rkt b/syndicate/test/core/responsibility-transfer-1.rkt new file mode 100644 index 0000000..c1b3b6d --- /dev/null +++ b/syndicate/test/core/responsibility-transfer-1.rkt @@ -0,0 +1,33 @@ +#lang imperative-syndicate/test-implementation +;; See .../syndicate/examples/actor/example-responsibility-transfer-1.rkt + +(test-case + [(spawn #:name 'demand-watcher + (during/spawn 'demand + #:name (gensym 'intermediate-demand-asserter) + (assert 'intermediate-demand))) + + (spawn #:name 'intermediate-demand-watcher + (during/spawn 'intermediate-demand + #:name (gensym 'supply-asserter) + (assert 'supply))) + + (spawn* #:name 'driver + (react (on (asserted 'supply) (displayln "Supply asserted.")) + (on (retracted 'supply) (displayln "Supply retracted."))) + (until (asserted (observe 'demand))) + (displayln "Asserting demand.") + (assert! 'demand) + (until (asserted 'supply)) + (displayln "Glitching demand.") + (retract! 'demand) + (flush!) + (assert! 'demand) + (displayln "Demand now steady."))] + no-crashes + (expected-output "Asserting demand." + "Supply asserted." + "Glitching demand." + "Demand now steady." + "Supply retracted." + "Supply asserted.")) diff --git a/syndicate/test/core/responsibility-transfer-2.rkt b/syndicate/test/core/responsibility-transfer-2.rkt new file mode 100644 index 0000000..5f0b86f --- /dev/null +++ b/syndicate/test/core/responsibility-transfer-2.rkt @@ -0,0 +1,71 @@ +#lang imperative-syndicate/test-implementation +;; Suite of four related tests. +;; See .../syndicate/examples/actor/example-responsibility-transfer-2.rkt + +(test-case + [(spawn #:name 'factory-1 + (on (asserted (list 'X 1)) + (spawn #:name 'service-1 + #:assertions [(observe (list 'X 1))] ;; (A) + (stop-when (retracted (list 'X 1))) ;; (B) + (on (message 'dummy))) + (stop-current-facet))) + (spawn (on (asserted (observe (list 'X $supplier))) + (printf "Supply ~v asserted.\n" supplier) + (assert! (list 'X supplier))) + (on (retracted (observe (list 'X $supplier))) + (printf "Supply ~v retracted.\n" supplier)))] + no-crashes + (expected-output "Supply 1 asserted.")) + +(test-case + [(spawn #:name 'factory-1 + (on (asserted (list 'X 1)) + (spawn #:name 'service-1 + ;; #:assertions [(observe (list 'X 1))] ;; (A) + (stop-when (retracted (list 'X 1))) ;; (B) + (on (message 'dummy))) + (stop-current-facet))) + (spawn (on (asserted (observe (list 'X $supplier))) + (printf "Supply ~v asserted.\n" supplier) + (assert! (list 'X supplier))) + (on (retracted (observe (list 'X $supplier))) + (printf "Supply ~v retracted.\n" supplier)))] + no-crashes + (expected-output "Supply 1 asserted." + "Supply 1 retracted." + "Supply 1 asserted.")) + +(test-case + [(spawn #:name 'factory-1 + (on (asserted (list 'X 1)) + (spawn #:name 'service-1 + #:assertions [(observe (list 'X 1))] ;; (A) + ;; (stop-when (retracted (list 'X 1))) ;; (B) + (on (message 'dummy))) + (stop-current-facet))) + (spawn (on (asserted (observe (list 'X $supplier))) + (printf "Supply ~v asserted.\n" supplier) + (assert! (list 'X supplier))) + (on (retracted (observe (list 'X $supplier))) + (printf "Supply ~v retracted.\n" supplier)))] + no-crashes + (expected-output "Supply 1 asserted." + "Supply 1 retracted.")) + +(test-case + [(spawn #:name 'factory-1 + (on (asserted (list 'X 1)) + (spawn #:name 'service-1 + ;; #:assertions [(observe (list 'X 1))] ;; (A) + ;; (stop-when (retracted (list 'X 1))) ;; (B) + (on (message 'dummy))) + (stop-current-facet))) + (spawn (on (asserted (observe (list 'X $supplier))) + (printf "Supply ~v asserted.\n" supplier) + (assert! (list 'X supplier))) + (on (retracted (observe (list 'X $supplier))) + (printf "Supply ~v retracted.\n" supplier)))] + no-crashes + (expected-output "Supply 1 asserted." + "Supply 1 retracted.")) diff --git a/syndicate/test/core/simple-addition.rkt b/syndicate/test/core/simple-addition.rkt new file mode 100644 index 0000000..f894074 --- /dev/null +++ b/syndicate/test/core/simple-addition.rkt @@ -0,0 +1,13 @@ +#lang imperative-syndicate/test-implementation + +(test-case + [(assertion-struct one-plus (n m)) + (spawn #:name 'add1-server + (during/spawn (observe (one-plus $n _)) + #:name (list 'solving 'one-plus n) + (assert (one-plus n (+ n 1))))) + (spawn #:name 'client-process + (stop-when (asserted (one-plus 3 $value)) + (printf "1 + 3 = ~a\n" value)))] + no-crashes + (expected-output "1 + 3 = 4")) diff --git a/syndicate/test/core/simple-box-and-client.rkt b/syndicate/test/core/simple-box-and-client.rkt new file mode 100644 index 0000000..106cf0a --- /dev/null +++ b/syndicate/test/core/simple-box-and-client.rkt @@ -0,0 +1,29 @@ +#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 "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")) diff --git a/syndicate/test/speed/speed-box-and-client.rkt b/syndicate/test/speed/speed-box-and-client.rkt new file mode 100644 index 0000000..c69da09 --- /dev/null +++ b/syndicate/test/speed/speed-box-and-client.rkt @@ -0,0 +1,22 @@ +#lang imperative-syndicate/test-implementation + +(let ((N 25000)) + (test-case + ;; Box-and-client speed test + [(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) N)) + (on (message (set-box $new-value)) + (current-value new-value))) + (spawn (stop-when (retracted (observe (set-box _)))) + (on (asserted (box-state $v)) + (send! (set-box (+ v 1)))))] + no-crashes + (expected-output) + (it "should be reasonably quick" + (log-info "Rough box-and-client speed: ~a cycles in ~a ms = ~a Hz" + N + (test-run-time) + (/ N (/ (test-run-time) 1000.0)))))) diff --git a/syndicate/test/speed/speed-message-sending.rkt b/syndicate/test/speed/speed-message-sending.rkt new file mode 100644 index 0000000..87e3740 --- /dev/null +++ b/syndicate/test/speed/speed-message-sending.rkt @@ -0,0 +1,16 @@ +#lang imperative-syndicate/test-implementation +;; Rough message send speed test + +(let ((N 100000)) + (test-case + [(spawn (on (message $v) + (if (= v N) + (stop-current-facet) + (send! (+ v 1)))) + (on-start (send! 0)))] + no-crashes + (it "should be fairly quick" + (log-info "Rough message send speed: ~a msgs in ~a ms = ~a Hz" + N + (test-run-time) + (/ N (/ (test-run-time) 1000.0))))))