;; Fib server — long-lived process that computes fibonacci numbers on ;; request. Tests recursive function evaluation inside a server loop. (define er-fib-test-count 0) (define er-fib-test-pass 0) (define er-fib-test-fails (list)) (define er-fib-test (fn (name actual expected) (set! er-fib-test-count (+ er-fib-test-count 1)) (if (= actual expected) (set! er-fib-test-pass (+ er-fib-test-pass 1)) (append! er-fib-test-fails {:actual actual :expected expected :name name})))) (define fib-ev erlang-eval-ast) ;; Fib + server-loop source. Standalone so each test can chain queries. (define er-fib-server-src "Fib = fun (0) -> 0; (1) -> 1; (N) -> Fib(N-1) + Fib(N-2) end, FibSrv = fun () -> Loop = fun () -> receive {fib, N, From} -> From ! Fib(N), Loop(); stop -> ok end end, Loop() end") ;; Base cases. (er-fib-test "fib(0)" (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Srv ! {fib, 0, Me}, receive R -> Srv ! stop, R end")) 0) (er-fib-test "fib(1)" (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Srv ! {fib, 1, Me}, receive R -> Srv ! stop, R end")) 1) ;; Larger values. (er-fib-test "fib(10) = 55" (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Srv ! {fib, 10, Me}, receive R -> Srv ! stop, R end")) 55) (er-fib-test "fib(15) = 610" (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Srv ! {fib, 15, Me}, receive R -> Srv ! stop, R end")) 610) ;; Multiple sequential queries to one server. Sum to avoid dict-equality. (er-fib-test "sequential fib(5..8) sum" (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Srv ! {fib, 5, Me}, A = receive Ra -> Ra end, Srv ! {fib, 6, Me}, B = receive Rb -> Rb end, Srv ! {fib, 7, Me}, C = receive Rc -> Rc end, Srv ! {fib, 8, Me}, D = receive Rd -> Rd end, Srv ! stop, A + B + C + D")) 47) ;; Verify Fib obeys the recurrence — fib(n) = fib(n-1) + fib(n-2). (er-fib-test "fib recurrence at n=12" (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Srv ! {fib, 10, Me}, A = receive Ra -> Ra end, Srv ! {fib, 11, Me}, B = receive Rb -> Rb end, Srv ! {fib, 12, Me}, C = receive Rc -> Rc end, Srv ! stop, C - (A + B)")) 0) ;; Two clients each get their own answer; main sums the results. (er-fib-test "two clients sum" (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Client = fun (N) -> spawn(fun () -> Srv ! {fib, N, self()}, receive R -> Me ! {result, R} end end) end, Client(7), Client(9), {result, A} = receive M1 -> M1 end, {result, B} = receive M2 -> M2 end, Srv ! stop, A + B")) 47) ;; Trace queries via io-buffer. (er-fib-test "trace fib 0..6" (do (er-io-flush!) (fib-ev (str er-fib-server-src ", Me = self(), Srv = spawn(FibSrv), Ask = fun (N) -> Srv ! {fib, N, Me}, receive R -> io:format(\"~p \", [R]) end end, Ask(0), Ask(1), Ask(2), Ask(3), Ask(4), Ask(5), Ask(6), Srv ! stop, done")) (er-io-buffer-content)) "0 1 1 2 3 5 8 ") (define er-fib-test-summary (str "fib " er-fib-test-pass "/" er-fib-test-count))