-module(erab_fsm_test). -include_lib("eunit/include/eunit.hrl"). -include("pfcp_mock.hrl"). -define(U2C, {?TEID_U2C, ?ADDR_U2C}). -define(C2U, {?TEID_C2U, ?ADDR_C2U}). -define(A2U, {?TEID_A2U, ?ADDR_A2U}). -define(U2A, {?TEID_U2A, ?ADDR_U2A}). %% ------------------------------------------------------------------ %% setup/misc functions %% ------------------------------------------------------------------ -define(TC(Fun), {setup, fun start/0, fun stop/1, Fun}). start() -> %% mock the PFCP peer API pfcp_mock:mock_all(), %% start an E-RAB FSM {ok, Pid} = erab_fsm:start_link(?MODULE), Pid. stop(_Pid) -> pfcp_mock:unmock_all(). erab_fsm_info(Pid, Key) -> Info = erab_fsm:fetch_info(Pid), proplists:get_value(Key, Info). %% ------------------------------------------------------------------ %% testcase descriptions %% ------------------------------------------------------------------ erab_setup_test_() -> [{"E-RAB setup :: success", ?TC(fun test_erab_setup_success/1)}, {"E-RAB setup :: PFCP session establishment error", ?TC(fun test_erab_setup_pfcp_establish_error/1)}, {"E-RAB setup :: PFCP session modification error", ?TC(fun test_erab_setup_pfcp_modify_error/1)}]. erab_release_test_() -> [{"E-RAB RELEASE CMD :: success", ?TC(fun test_erab_release_cmd_success/1)}, {"E-RAB RELEASE IND :: success", ?TC(fun test_erab_release_ind_success/1)}, {"E-RAB release :: PFCP session deletion error", ?TC(fun test_erab_release_pfcp_delete_error/1)}]. erab_info_test_() -> [{"E-RAB info :: state", ?TC(fun test_erab_info_state/1)}, {"E-RAB info :: F-TEIDs", ?TC(fun test_erab_info_f_teid/1)}]. erab_shutdown_test_() -> [{"E-RAB shutdown (no session)", ?TC(fun test_erab_shutdown_no_session/1)}, {"E-RAB shutdown (expect session deletion)", ?TC(fun test_erab_shutdown_session_del/1)}]. %% ------------------------------------------------------------------ %% actual testcases %% ------------------------------------------------------------------ test_erab_setup_success(Pid) -> [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual(ok, erab_fsm:shutdown(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_setup_pfcp_establish_error(Pid) -> %% pfcp_peer:session_delete_req/1 shall not be called ok = pfcp_mock:unmock_req(session_delete_req, 1), %% pfcp_peer:session_establish_req/3 responds with a reject PDU = pfcp_mock:pdu_rsp_reject(session_establishment_response, ?SEID_Loc), pfcp_mock:mock_req(session_establish_req, PDU), unlink(Pid), %% we expect the FSM to terminate abnormally Error = {unexp_pdu, session_establish}, [?_assertEqual({error, Error}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_setup_pfcp_modify_error(Pid) -> %% pfcp_peer:session_modify_req/3 responds with a reject PDU = pfcp_mock:pdu_rsp_reject(session_modification_response, ?SEID_Loc), pfcp_mock:mock_req(session_modify_req, PDU), unlink(Pid), %% we expect the FSM to terminate abnormally Error = {unexp_pdu, session_modify}, [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual({error, Error}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_release_cmd_success(Pid) -> [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual(ok, erab_fsm:erab_release_cmd(Pid)), ?_assertEqual(ok, erab_fsm:erab_release_rsp(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_release_ind_success(Pid) -> [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual(ok, erab_fsm:erab_release_ind(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_release_pfcp_delete_error(Pid) -> %% pfcp_peer:session_delete_req/1 responds with a reject PDU = pfcp_mock:pdu_rsp_reject(session_deletion_response, ?SEID_Loc), pfcp_mock:mock_req(session_delete_req, PDU), unlink(Pid), %% we expect the FSM to terminate abnormally Error = {unexp_pdu, session_delete}, [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual({error, Error}, erab_fsm:erab_release_cmd(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_info_state(Pid) -> [?_assertEqual(erab_wait_setup_req, erab_fsm_info(Pid, state)), ?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual(erab_wait_setup_rsp, erab_fsm_info(Pid, state)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual(erab_setup, erab_fsm_info(Pid, state)), ?_assertEqual(ok, erab_fsm:erab_release_cmd(Pid)), ?_assertEqual(erab_wait_release_rsp, erab_fsm_info(Pid, state)), ?_assertEqual(ok, erab_fsm:erab_release_rsp(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_info_f_teid(Pid) -> [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual(?U2C, erab_fsm_info(Pid, f_teid_u2c)), ?_assertEqual(?A2U, erab_fsm_info(Pid, f_teid_a2u)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual(?U2A, erab_fsm_info(Pid, f_teid_u2a)), ?_assertEqual(?C2U, erab_fsm_info(Pid, f_teid_c2u)), ?_assertEqual(ok, erab_fsm:erab_release_cmd(Pid)), ?_assertEqual(ok, erab_fsm:erab_release_rsp(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_shutdown_no_session(Pid) -> %% pfcp_peer:session_delete_req/1 shall not be called ok = pfcp_mock:unmock_req(session_delete_req, 1), [?_assertEqual(ok, erab_fsm:shutdown(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. test_erab_shutdown_session_del(Pid) -> [?_assertEqual({ok, ?A2U}, erab_fsm:erab_setup_req(Pid, ?U2C)), ?_assertEqual({ok, ?C2U}, erab_fsm:erab_setup_rsp(Pid, ?U2A)), ?_assertEqual(ok, erab_fsm:shutdown(Pid)), ?_assertNot(erlang:is_process_alive(Pid))]. %% vim:set ts=4 sw=4 et: