Files
erlang/test/ezap_capability_tests.erl
zeekay 9ad5515323 ci: add rebar3 build/test CI, fix OTP 29 + test isolation
Build the ezap Erlang binding with rebar3 and run it green on modern OTP.

rebar.config: test-profile deps proper 1.5.0 + meck 1.2.0 (meck 1.0.0 fails
to compile on OTP 29 — legacy `catch` is now an error), CT dir test/.

.github/workflows/ci.yml: push-to-main + PR + workflow_dispatch, OTP 26/27
matrix via erlef/setup-beam, runs `rebar3 compile/eunit/ct`.

src/schema_zap.erl, test/test_zap.erl: strip fossil `-type({{record,_},...})`
attributes. Pre-OTP-27 epp split typed records into a separate record-type
attr with bare-integer annotations; OTP 29 erl_lint crashes on these
(erl_anno violation). Modern epp emits typed -record forms directly, so these
attrs are dead weight; the -record decls already carry the fields.

test isolation: ezap_promise_sup / ezap_capability_sup are locally registered,
but teardown used exit(Pid, normal) — a no-op against an exit-trapping
supervisor — leaking the registered name and failing the next test with
{already_started,_}. Add ezap_test_utils:stop_sup/1 (unlink+monitor+kill+wait)
and use it everywhere; thirdCap_test_/basicCap_test_ now start and stop their
own promise supervisor instead of relying on a leak from a prior test.

bin/run_test: erlang:get_stacktrace/0 (removed in OTP 24) -> Class:Error:Stack.
2026-06-20 21:33:37 -07:00

139 lines
4.8 KiB
Erlang

%%
%% Copyright 2013, Andreas Stenius <[email protected]>
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
-module(ezap_capability_tests).
-ifdef(TEST).
-export([basicCap_funs/0]).
-import(ezap_test_utils, [setup_meck/2, teardown_meck/1, stop_sup/1]).
-include_lib("eunit/include/eunit.hrl").
-include("include/ezap.hrl").
basicCap_test_() ->
{setup,
fun () ->
{ok, ProS} = ezap_promise_sup:start_link(),
{ProS, setup_meck(basicCap, basicCap_funs())}
end,
fun ({ProS, Mod}) ->
teardown_meck(Mod),
stop_sup(ProS)
end,
[fun () ->
{ok, Pid} = ezap_capability:start([basicCap, [test_zap:'BasicCap'()]]),
?assert(is_process_alive(Pid)),
ok = ezap_capability:stop(Pid),
receive after 100 -> ok end, %% ugly hack, I know..
?assert(not is_process_alive(Pid))
end,
fun () ->
S = test_zap:'BasicCap'(),
{ok, Pid} = ezap_capability:start_link([basicCap, [S]]),
test_basicCap_add(Pid, S, 123, 456)
end
]}.
thirdCap_test_() ->
{setup,
fun () ->
{ok, ProS} = ezap_promise_sup:start_link(),
{ProS, setup_meck(thirdCap, thirdCap_funs())}
end,
fun ({ProS, Mod}) ->
teardown_meck(Mod),
stop_sup(ProS)
end,
[fun () ->
S = test_zap:'ThirdCap'(),
{ok, Pid} = ezap_capability:start_link([thirdCap, [S], {init, third}]),
test_basicCap_add(Pid, test_zap:'BasicCap'(), 333, 666),
test_otherCap_sqroot(Pid, test_zap:'OtherCap'(), 4),
test_thirdCap_square(Pid, S, 5)
end
]}.
basicCap_funs() ->
[{handle_call, fun ('BasicCap', add, Params, Result, undefined) -> {basicCap_add(Params, Result), undefined};
('BasicCap', sub, Params, Result, undefined) -> {basicCap_sub(Params, Result), undefined}
end}].
basicCap_add(Params, Results) ->
ezap:set(result,
ezap:get(a, Params)
+ ezap:get(b, Params),
Results).
basicCap_sub(Params, Results) ->
ezap:set(result,
ezap:get(a, Params)
- ezap:get(b, Params),
Results).
test_basicCap_add(Pid, S, A, B) ->
{ok, Params} = ezap:set_root(['BasicCap', [add, '$Params']], test_zap),
ok = ezap:set(a, A, Params),
ok = ezap:set(b, B, Params),
Req = #rpc_call{
interface = S#schema_node.id,
method = 0,
params = Params
},
Promise = ezap_capability:send(Pid, Req),
{ok, Result} = ezap_promise:wait(Promise, 1000),
?assertEqual(A+B, ezap:get(result, Result)).
otherCap_sqroot(Params, Results) ->
Sqrt = math:sqrt(ezap:get(a, Params)),
ezap:set(root1, Sqrt, Results),
ezap:set(root2, -Sqrt, Results).
test_otherCap_sqroot(Pid, S, A) ->
{ok, Params} = ezap:set_root(['OtherCap', [sqroot, '$Params']], test_zap),
ok = ezap:set(a, A, Params),
{ok, Result} = ezap_promise:wait(
ezap_capability:send(
Pid, #rpc_call{ interface = S#schema_node.id,
method = 0, params = Params }),
1000),
R1 = ezap:get(root1, Result),
R2 = ezap:get(root2, Result),
?assertEqual(float(-A), R1*R2).
thirdCap_funs() ->
[{init, fun (third) -> {state, []} end},
{handle_call,
fun ('BasicCap', add, Params, Result, {state, []}) -> {basicCap_add(Params, Result), {state, []}};
('OtherCap', sqroot, Params, Result, {state, []}) -> {otherCap_sqroot(Params, Result), {state, []}};
('ThirdCap', square, Params, Result, {state, []}) -> {thirdCap_square(Params, Result), {state, []}}
end}].
thirdCap_square(Params, Results) ->
A = ezap:get(a, Params),
ezap:set(sq, A * A, Results).
test_thirdCap_square(Pid, S, A) ->
{ok, Params} = ezap:set_root(['ThirdCap', [square, '$Params']], test_zap),
ok = ezap:set(a, A, Params),
{ok, Result} = ezap_promise:wait(
ezap_capability:send(
Pid, #rpc_call{ interface = S#schema_node.id,
method = 0, params = Params }),
1000),
?assertEqual(A*A, ezap:get(sq, Result)).
-endif.