Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
128 lines
3.3 KiB
Plaintext
128 lines
3.3 KiB
Plaintext
;; Ping-pong program — two processes exchange N messages, then signal
|
|
;; main via separate `ping_done` / `pong_done` notifications.
|
|
|
|
(define er-pp-test-count 0)
|
|
(define er-pp-test-pass 0)
|
|
(define er-pp-test-fails (list))
|
|
|
|
(define
|
|
er-pp-test
|
|
(fn
|
|
(name actual expected)
|
|
(set! er-pp-test-count (+ er-pp-test-count 1))
|
|
(if
|
|
(= actual expected)
|
|
(set! er-pp-test-pass (+ er-pp-test-pass 1))
|
|
(append! er-pp-test-fails {:actual actual :expected expected :name name}))))
|
|
|
|
(define pp-ev erlang-eval-ast)
|
|
|
|
;; Three rounds of ping-pong, then stop. Main receives ping_done and
|
|
;; pong_done in arrival order (Ping finishes first because Pong exits
|
|
;; only after receiving stop).
|
|
(define
|
|
er-pp-program
|
|
"Me = self(),
|
|
Pong = spawn(fun () ->
|
|
Loop = fun () ->
|
|
receive
|
|
{ping, From} -> From ! pong, Loop();
|
|
stop -> Me ! pong_done
|
|
end
|
|
end,
|
|
Loop()
|
|
end),
|
|
Ping = fun (Target, K) ->
|
|
if K =:= 0 -> Target ! stop, Me ! ping_done;
|
|
true -> Target ! {ping, self()}, receive pong -> Ping(Target, K - 1) end
|
|
end
|
|
end,
|
|
spawn(fun () -> Ping(Pong, 3) end),
|
|
receive ping_done -> ok end,
|
|
receive pong_done -> both_done end")
|
|
|
|
(er-pp-test
|
|
"ping-pong 3 rounds"
|
|
(get (pp-ev er-pp-program) :name)
|
|
"both_done")
|
|
|
|
;; Count exchanges via io-buffer — each pong trip prints "p".
|
|
(er-pp-test
|
|
"ping-pong 5 rounds trace"
|
|
(do
|
|
(er-io-flush!)
|
|
(pp-ev
|
|
"Me = self(),
|
|
Pong = spawn(fun () ->
|
|
Loop = fun () ->
|
|
receive
|
|
{ping, From} -> io:format(\"p\"), From ! pong, Loop();
|
|
stop -> Me ! pong_done
|
|
end
|
|
end,
|
|
Loop()
|
|
end),
|
|
Ping = fun (Target, K) ->
|
|
if K =:= 0 -> Target ! stop, Me ! ping_done;
|
|
true -> Target ! {ping, self()}, receive pong -> Ping(Target, K - 1) end
|
|
end
|
|
end,
|
|
spawn(fun () -> Ping(Pong, 5) end),
|
|
receive ping_done -> ok end,
|
|
receive pong_done -> ok end")
|
|
(er-io-buffer-content))
|
|
"ppppp")
|
|
|
|
;; Main → Pong directly (no Ping process). Main plays the ping role.
|
|
(er-pp-test
|
|
"main-as-pinger 4 rounds"
|
|
(pp-ev
|
|
"Me = self(),
|
|
Pong = spawn(fun () ->
|
|
Loop = fun () ->
|
|
receive
|
|
{ping, From} -> From ! pong, Loop();
|
|
stop -> ok
|
|
end
|
|
end,
|
|
Loop()
|
|
end),
|
|
Go = fun (K) ->
|
|
if K =:= 0 -> Pong ! stop, K;
|
|
true -> Pong ! {ping, Me}, receive pong -> Go(K - 1) end
|
|
end
|
|
end,
|
|
Go(4)")
|
|
0)
|
|
|
|
;; Ensure the processes really interleave — inject an id into each
|
|
;; ping and check we get them all back via trace (the order is
|
|
;; deterministic under our sync scheduler).
|
|
(er-pp-test
|
|
"ids round-trip"
|
|
(do
|
|
(er-io-flush!)
|
|
(pp-ev
|
|
"Me = self(),
|
|
Pong = spawn(fun () ->
|
|
Loop = fun () ->
|
|
receive
|
|
{ping, From, Id} -> From ! {pong, Id}, Loop();
|
|
stop -> ok
|
|
end
|
|
end,
|
|
Loop()
|
|
end),
|
|
Go = fun (K) ->
|
|
if K =:= 0 -> Pong ! stop, done;
|
|
true -> Pong ! {ping, Me, K}, receive {pong, RId} -> io:format(\"~p \", [RId]), Go(K - 1) end
|
|
end
|
|
end,
|
|
Go(4)")
|
|
(er-io-buffer-content))
|
|
"4 3 2 1 ")
|
|
|
|
(define
|
|
er-pp-test-summary
|
|
(str "ping-pong " er-pp-test-pass "/" er-pp-test-count))
|